Category Archives: Azure MFA

Exploring Azure MFA sign-in failures using Log Analytics

Most IT admins, pros and end users from organizations that use Office 365 and Azure AD will by now have heard about the big Azure MFA outage on Monday November 19. When something like this happens, it is important to get insights on which users that were affected, and in what type of scenarios they most experienced the problem. Microsoft MVP Tony Redmond wrote a useful blog post (https://office365itpros.com/2018/11/21/reporting-mfa-enabled-accounts/) on how to report on possible/potentially affected and MFA enabled users, and how to disable and re-enable those users. But many organizations are now using Conditional Access policies using Azure AD Premium, so this will be of limited help for those.

If I could wish one thing from Microsoft for Christmas this year, it would be to be able to manage MFA and Conditional Access policies with Azure AD PowerShell and Microsoft Graph! Admins could then run “break-the-glass” administrative users (or even “break-the-glass service principals”) to disable/re-enable policies when big MFA outages happens. A good CA policy design, trusting compliant devices and secure locations could also go a long way in mitigating such big outage problems.

Tony’s blog post made me think about the feature I recently activated, on integrating Azure AD Activity Logs to Azure Log Analytics, you can read more about this here: https://gotoguy.blog/2018/11/06/get-started-with-integration-of-azure-ad-activity-logs-to-azure-log-analytics/

By exploring the Sign-in logs in Log Analytics I could get some more insights into how my organization was affected by the MFA outage on November 19. Please see the above blog post on how to get started setting up this integration, the rest of this blog post will show some sample queries for the SigninLogs.

Querying the SigninLogs for failed and interrupted sign-ins

All the queries seen below are shown in screenshot images, but I have listed all them for you to copy at the end of the blog post.

First I can take a look at the SigninLogs for the specific day of 19th November, and the grouping on the result type and description of the sign-in events. For example I can see that there is a high number of event 50074: User did not pass the MFA challenge. Interestingly there is also a relatively high number of invalid username or password, that could be a separate issue but could also be that users that fails MFA sign-ins tries to log in again thinking they had wrong password first time.

image

Changing that query a little, I can exclude the successful sign-ins (ResultType 0), and sort on the most count of failures. Two of the events of most interest here is 50074 and 50076:

image

In this next query I focus on the “50074: User did not pass the MFA challenge” error. By increasing the time range to last 31 days, and adding a bin(TimeGenerated, 1d) to the summarize group, I’ll be able to see the count of this error on each day in the last month. This will give me a baseline, and we can see that on the 19th this number spikes. I have added a render to timechart for graphical display. There are also some other days where this number increases, I can look into more insights for that if I want as well, but for now I will focus on the 19th.

image

Back to the time range of the 19th of November, I can modify the summarize to group by each hour, by using bin(TimeGenerated, 1h). This will show me how the problems evolved during the day. Must errors occurred about 10 am in the morning:

image

Lets look at some queries for how this error affected my environment. First I can group on the Users and how many errors they experience. Some users were really persistent in trying to get through the MFA error. I have masked the real names. We also see some admin accounts but admins quickly recognized that something was wrong, and actively sought information on the outage. By midday most users were notified on the on-going outage and the number of errors slowly decrease during the day.

image

In this next query, I group on the Apps the users tried to reach:

image

And in this following query, what kind of Client App they used. It would be normal that Browser is quite high, as mobile apps and desktop clients are more likely to have valid refresh tokens.

image

In this query I can look into the device operating system the users tried to sign in from:

2018-11-21_22-05-27

In the following query I can look at which network the users tried to log in from, by identifying IP address:

image

And in this query we can get more location details from where users tried to sign in:

2018-11-21_22-07-17

Summary

Querying Log Analytics for Sign-in events as shown above can provide valuable insights into how such an outage can affect users. This can also give me some input on how to design Conditional Access policies. Querying this data over time can also provide a baseline for normal operations in your environment, and make it easier to set alert thresholds if you want to get alerts when number of failures inside a time interval gets higher than usual. Using Azure Monitor and action groups you can be pro-active and be notified if something similar should occur again.

Here are all the queries shown above:

// Look at SigninLogs for a custom date time interval and group by sign in results
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| summarize count() by ResultType, ResultDescription

// Exclude successful signins and format results with sorting
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType != "0" 
| summarize FailedSigninCount = count() by ResultDescription, ResultType 
| sort by FailedSigninCount desc

// Look at User did not pass the MFA challenge error last month to see trend
// and present to line chart group by each 1 day
SigninLogs
| where TimeGenerated >= ago(31d)
| where ResultType == "50074"
| summarize FailedSigninCount = count() by ResultDescription, bin(TimeGenerated, 1d)
| render timechart

// Look at User did not pass the MFA challenge error on the MFA outage day
// and present to line chart group by each 1 hour to see impact during day
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074" 
| summarize FailedSigninCount = count() by ResultDescription, bin(TimeGenerated, 1h)
| render timechart

// Look at User did not pass the MFA challenge error on the MFA outage day
// and group on users to see affected users
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074"
| summarize FailedSigninCount = count() by UserDisplayName
| sort by FailedSigninCount desc

// Look at User did not pass the MFA challenge error on the MFA outage day
// and group on Apps to see affected applications the users tried to sign in to
SigninLogs
| where TimeGenerated  between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074"
| summarize FailedSigninCount = count() by AppDisplayName
| sort by FailedSigninCount desc

// Look at User did not pass the MFA challenge error on the MFA outage day
// and group on client apps to see affected apps the users tried to sign in from
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074"
| summarize FailedSigninCount = count() by ClientAppUsed
| sort by FailedSigninCount desc

// Look at User did not pass the MFA challenge error on the MFA outage day
// and group on device operating system to see affected platforms
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074"
| summarize FailedSigninCount = count() by tostring(DeviceDetail.operatingSystem)
| sort by FailedSigninCount desc

// Look at User did not pass the MFA challenge error on the MFA outage day
// and group on IP address to see from which network users tried to sign in from
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074"
| summarize FailedSigninCount = count() by IPAddress
| sort by FailedSigninCount desc

// Look at User did not pass the MFA challenge error on the MFA outage day
// and group on users location details to see which country, state and city users tried to sign in from
SigninLogs
| where TimeGenerated between(datetime("2018-11-19 00:00:00") .. datetime("2018-11-19 23:59:59")) 
| where ResultType == "50074"
| summarize FailedSigninCount = count() by tostring(LocationDetails.countryOrRegion), tostring(LocationDetails.state), tostring(LocationDetails.city)
| sort by FailedSigninCount desc

Azure MFA Report Dashboard in Azure Portal–The Good, The Bad and The Ugly

If you are working with EMS and implementing Azure AD, Intune, MDM, MAM, Information Protection and more, you can build yourself some great dashboards in the Azure Portal using tiles and pin blades to your customized dashboard. This is an example from my own workplace:

image

Often when I work with projects implementing Identity & Access, Conditional Access and Azure MFA, I wish I could have a dashboard to report on MFA registration, and be able to pin that to my EMS dashboard as shown above.

It might be in the future that Azure MFA registrations and methods will be native in the portal, but for now this information have to be retreived in another way. In this blog post I will show you how you can set up a solution for showing this information. I will use the Markdown Tile from the gallery for displaying this information, and in the end it will look like this:

I referred in the title of this blog post to the good, the bad and the ugly, and by that I mean the process of setting this up, because it starts easy enough in the beginning but it will get more “ugly” in the end 😉

The Good – Setting up the Markdown Tile

I will use the Markdown Tile for the content in my customized dashboard in my Azure Portal. The first part is easy to set up, just click Edit and find the Markdown tile from the gallery, as shown below:

image

Drag the tile to a place you want it on your dashboard, and the Edit the title, subtitle and content as prompted:

image

There is a sample content provided, other than that you can write your own markdown. I will not get into details on markdown format here, there is a lot of good guides for learning the format, for example this: https://guides.github.com/features/mastering-markdown/. I will however provide you with a sample for reporting MFA registrations and default methods. This is how I set up my markdown tile:

image

And here is a link to my github repository where you can get the complete MFAReport.md file sample:

https://github.com/skillriver/AzureMFADashboard/blob/master/MFAReport.md

Now we need to fill that markdown tile with some real Azure AD MFA report data to report on.

The Bad – PowerShell Script for getting MFA registration and methods to Markdown

So the “bad” news is that we are reliant on running some Azure AD PowerShell commands for getting user details for MFA registration and methods. For now we are also reliant on the Azure AD v1 PowerShell (MSOnline) Module, as the new v2 AzureAD Module does not yet have any methods to get MFA authentication data. We cannot use the Microsoft Graph API either to get MFA user data, but I expect that to change in the future.

So lets look at the script I use, and after authenticating and connecting to Azure AD in my tenant with Connect-MSOLService, I will run the following commands to get details from each user where there has been configured one or more StrongAuthenticationMethods, and Group on those methods and save the results to a hash table. The results are stored in the $authMethodsRegistered object variable. Similarly I run the command once more, filtering on only showing the methods that are set to default for each user, and save to the $authMethodsDefault variable.

# Connect to MSOnline PowerShell (Azure AD v1)
Connect-MsolService

# Get MFA Methods Registered as Hash Table
$authMethodsRegistered = Get-MsolUser -All | Where-Object {$_.StrongAuthenticationMethods -ne $null} | Select-Object -Property UserPrincipalName -ExpandProperty StrongAuthenticationMethods `
| Group-Object MethodType -AsHashTable -AsString

# Get Default MFA Methods as Hash Table
$authMethodsDefault = Get-MsolUser -All | Where-Object {$_.StrongAuthenticationMethods -ne $null} | Select-Object -Property UserPrincipalName -ExpandProperty StrongAuthenticationMethods `
| Where-Object {$_.IsDefault -eq $true} | Group-Object MethodType -AsHashTable -AsString

# Create a Custom Object for MFA Data
$authMethodsData = New-Object PSObject
$authMethodsData | Add-Member -MemberType NoteProperty -Name AuthPhoneRegistered -Value $authMethodsRegistered.TwoWayVoiceMobile.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name AuthPhoneAppRegistered -Value $authMethodsRegistered.PhoneAppOTP.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name OfficePhoneRegistered -Value $authMethodsRegistered.TwoWayVoiceOffice.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name AlternatePhoneRegistered -Value $authMethodsRegistered.TwoWayVoiceAlternateMobile.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name OneWaySMSDefault –Value $authMethodsDefault.OneWaySMS.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name PhoneAppNotificationDefault –Value $authMethodsDefault.PhoneAppNotification.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name PhoneAppOTPDefault –Value $authMethodsDefault.PhoneAppOTP.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name TwoWayVoiceMobileDefault –Value $authMethodsDefault.TwoWayVoiceMobile.Count
$authMethodsData | Add-Member -MemberType NoteProperty -Name TwoWayVoiceOfficeDefault –Value $authMethodsDefault.TwoWayVoiceOffice.Count

# Write to Markdown file
"## MFA Authentication Methods`n" | Set-Content .\MFAReport.md -Force -Encoding UTF8
"### Registered`n" | Add-Content .\MFAReport.md -Encoding UTF8
"The following methods has been registered by users:`n" | Add-Content .\MFAReport.md -Encoding UTF8
"| Method | Count |" | Add-Content .\MFAReport.md -Encoding UTF8
"|:-----------|:-----------|" | Add-Content .\MFAReport.md -Encoding UTF8
"| Authentication Phone | " + [string]$authMethodsData.AuthPhoneRegistered + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| Phone App | " + [string]$authMethodsData.AuthPhoneAppRegistered + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| Alternate Phone | " + [string]$authMethodsData.AlternatePhoneRegistered + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| Office Phone | " + [string]$authMethodsData.OfficePhoneRegistered + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"" | Add-Content .\MFAReport.md -Encoding UTF8
"### Default Method" | Add-Content .\MFAReport.md -Encoding UTF8
"The following methods has been configured as default by users:" | Add-Content .\MFAReport.md -Encoding UTF8
"" | Add-Content .\MFAReport.md -Encoding UTF8
"| Method | Count |" | Add-Content .\MFAReport.md -Encoding UTF8
"|:-----------|:-----------|" | Add-Content .\MFAReport.md -Encoding UTF8
"| OneWay SMS | " + [string]$authMethodsData.OneWaySMSDefault + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| Phone App Notification | " + [string]$authMethodsData.PhoneAppNotificationDefault + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| Phone App OTP | " + [string]$authMethodsData.PhoneAppOTPDefault + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| TwoWay Voice Mobile | " + [string]$authMethodsData.TwoWayVoiceMobileDefault + " |" | Add-Content .\MFAReport.md -Encoding UTF8
"| TwoWay Voice Office Phone | " + [string]$authMethodsData.TwoWayVoiceOfficeDefault + " |`n" | Add-Content .\MFAReport.md -Encoding UTF8
"Last reported " + [string](Get-Date) | Add-Content .\MFAReport.md -Encoding UTF8

"" | Add-Content .\MFAReport.md

The complete PowerShell script can be found at my GitHub repository here:

https://github.com/skillriver/AzureMFADashboard/blob/master/MFAStrongAuthenticationUserReport.ps1

So now we have a script where we can get MFA authentication details for each user and create a markdown file that we can use in the tile in the Azure Portal custom dashboard. But it is all a manual process now, and it works fine for an ad hoc update. If we want to automate however, we have to get into the “ugly” stuff 😉

The Ugly – Automating Markdown creation and update Dashboard

This part requires multiple steps. First we need to schedule and run the PowerShell commands from above. Then we need to find a way to update the customized dashboard tile with the updated markdown file. To summary, this is what we need now:

  • Schedule the PowerShell script to run automatically. We can use Azure Automation for that.
  • Programmatically change the markdown tile in the customized dashboard. We can use Azure Resource Manager Rest API for that.

Lets get into the Azure Automation solution first. To run a PowerShell script I will need to create a Runbook, and in that Runbook I need to authenticate to Azure AD. I can define a Credential Asset with a username and password for a global admin user, but I like to use the least privilege possible, and besides that all my global admins are either protected by Azure AD PIM and/or MFA, so that won’t work. I prefer to use a service principal whereever possible, but after testing extensively with Connect-MSOLService that is not supported either.

So I tested with a dedicated Azure AD credential account, first by only adding the user to the Directory Readers role. I was able to list all users with Get-MSOLUser, but not any StrongAuthentication info. Neither did it work with Security Readers. In the end I added the user account to User Administrator role in Azure AD, and I was successful getting StrongAuthentication methods.

So, in my automation accont I will add or reuse my credentials:

image

Next, I will create a new PowerShell script based Runbook, basically I will use the PowerShell script from earlier in the blog, but with a couple of added parameter and getting the credential using the Get-PSAutomationCredential method. This is how it looks, you will get link to the complete script later:

image

And after testing, I can see that I successfully will get the MFAReport.md content (added a Get-Content .\MFAReport.md at the end to display the output):

image

Now that we have a solution for running the PowerShell script and generating the markdown file, the next part is how to update that data in the custom dashboard. And for that we need to look into programatically changing Azure Portal dashboards. There is a good resource and starting point for that in this article: https://docs.microsoft.com/en-us/azure/azure-portal/azure-portal-dashboards-create-programmatically.

First you need to share the custom dashboard, remember to include the markdown tile we set up in the first part of this blog post. At the top in the portal dashboard, select the Share button:

image

By sharing the dashboard will published as an Azure resource. Specify a name, select the subscription and either use the default dashboard resource group or select an existing one:

image

Go to Resource Explorer in the Portal:

image

Navigate to Subscriptions, Resource Groups, and find the resource group and resource containing the custom dashboard. From there you will be able to see the JSON definition of the dashboard and specifically the markdown tile containing the content we want to update:

image

So for next process now we need to copy this complete JSON definition containing all your tiles including the markdown tile. Locally on your computer, create a .json file in your favorite JSON editor, I use Visual Studio Code for this, and paste in the content. I have named my file DeploymentTemplateMFAReport.json.

Now we need to change this template to be ready for deployment, and for that we need to add or change a couple of things. First, in the start of the JSON file, add schema and versioning, and parameters, variables and resources section like I have shown below in line 1-17:

image

I have chosen to use 3 parameters, the markdown content itself, and name of the dashboard and the title of the dashboard.

Next, find the tile for the markdown content, and change the content value to the value of the parameter, like I have done at line 113 here:

image

And last, at the end of the json template, add and change the following settings, I have used my parameters for the dashboard name and the dashboard title here in the lines 401-411:

image

My deployment template for the customized dashboard is now completely general and can be used in every environment. In fact you are welcome to borrow and use my template from above her, I have included it in my github repository:

https://github.com/skillriver/AzureMFADashboard/blob/master/DeploymentTemplateMFAReport.json

Working locally in my Visual Studio Code editor, I can now test the deployment using Azure PowerShell, as shown below and described with these simple steps:

  1. Connect to Azure Resource Manager and select the Subscription
  2. Specify a variable for the Resource Group you want to deploy to
  3. The MFAreport.md file (which we created earlier) need some converting to JSON format, I’m removing all espace characters and any uneeded special characters
  4. Specify variable names your environment for name and title for the dashboard
  5. Deploy the custom dashboard to the resource group

image

However, now that we can test the deployment, I want to schedule a deployment using Azure Automation, and I will continue on my previous runbook from before. But first we need to set up some connections for authenticating to Azure and some variables.

I Azure Automation we can create an Azure Run As Account, this will also create a service principal. If you navigate to your Automation Account in the Azure Portal, and go to the section called Run as accounts, you can create an Azure Run As Account automatically, as I have done here:

image

If I look more closely at this generated Run As Account, I can see details for Azure AD App Registration, Service Principal, Certificate and more. This account will also automatically be assigned Contributor role for my Azure Subscription. If you want more control over Azure Run As Accounts, you can create your own as described in the following article: https://docs.microsoft.com/en-us/azure/automation/automation-create-runas-account

image

I will use this Azure Run As account in my environment to deploy the dashboard resource, I’ll just need to make sure the account has contributor access to the resource group. Next I will set ut a few variables under the Variables section for my Automation Account, I will use these variables when I deploy the resource:

image

Now we are ready to finally put together the complete Runbook and test it. You will have the complete link later in the blog post, but I will share some screenshots first:

After I’ve connected with Connect-MSOLService I’m creating a variable for the markdown content, so I’ve changed from earlier when I saved a .md file temporarily, now I just adding lines using the newline special character (`n):

image

The next part is for logging in to Azure (using the Azure Run As Account mentioned above), and then getting my variables ready for deployment:

image

Then I convert the markdown content to Json format, and removing any escape characters that I don’t need:

image

And then deploy the dashboard resource with parameters for markdown content and dashboard name & title. Note that I’m using my deployment template as a source from my github repository via the TemplateUri property:

image

You can use any TemplateUri you want, for example from a more private source like a storage account blob etc.

Testing the Runbook gives the following output, which shows it was successful:

image

When I now go and refresh the dasboard in the portal, I can see that the markdown tile has been updated:

image

That leaves me with just publishing and scheduling the runbook:

image

When creating a new schedule specify a name and recurrence:

image

Link the schedule to the runbook and any needed parameters, I have to specify my credential that are allowed to Connect-MSOLService:

image

That concludes this lengthy blog post. The script will now run regularly and update my custom markdown tile with MFA report data.

Here is the link to the PowerShell script used in my Azure Automation runbook, enjoy your MFA Reporting!

https://github.com/skillriver/AzureMFADashboard/blob/master/MFAStrongAuthenticationUserReportAutomation.ps1

 

Exchange Online PowerShell with Modern Authentication and Azure MFA available!

A while back I wrote a blog post on how you could use Azure AD Privileged Identity Management to indirectly require MFA for Office 365 Administrator Roles activation before they connected to Exchange online via Remote PowerShell. See https://gotoguy.blog/2016/09/09/how-to-enable-azure-mfa-for-online-powershell-modules-that-dont-support-mfa/.

In december a new Exchange Online Remote PowerShell Module was released (in preview), https://technet.microsoft.com/en-us/library/mt775114(v=exchg.160), that uses Modern Authentication and that supports Azure Multi-Factor Authentication. Lets try it out:

First you need to verify that Modern Authentication is enabled in your Exchange Online organization, as this is not enabled by default: https://support.office.com/en-us/article/Enable-Exchange-Online-for-modern-authentication-58018196-f918-49cd-8238-56f57f38d662?ui=en-US&rs=en-US&ad=US

In my Exchange Online organization I verify that Modern Authentication is enabled:

image

Next logon to your Exchange Online Admin Center, and go to Hybrid to download and configure the Exchange Online PowerShell Module:

image

The configure button activates a click once install:

image

After installation I’m ready to connect:

image

Lets try it out on a MFA enabled admin user:

image

And as expected, I’m prompted to provide my verification code:

image

And after verification I can administer Exchange Online:

image

So with that we are finally able to log in to Exchange Online PowerShell more securely with Azure Multi-Factor Authentication as long as Modern Authentication is enabled for your organization!

Speaking at #ExpertsLive 2016 Netherlands

Next week at Tuesday 22nd of November I will be back speaking at ExpertsLive 2016, at CineMed Ede, Netherlands. After my first visit and speaking there last year, I always wanted to go back to this great community event, and I’m very happy and honored to be invited to speak again.

ExpertsLive NL 2016 will feature over 50 sessions, plus Keynote and Closing note, in as much as 9 different tracks ranging from Azure and Azure Stack, to Managebility, Automation, Windows Server 2016, Office 365, Security and Windows 10! In addition there will be great sponsors and networking. What more can you ask of a conference. There will be over 1000 attendees mostly from Netherlands, but also from visiting nearby countries.

My session will be on Azure Active Directory and how you can perform Premium Management and Protection of Identity and Access with Azure AD, covering solutions like Privileged Identity Management, Identity Protection, Multi-Factor Authentication and Azure AD Connect Health. It is very important to protect your identity now, let me show you how, and I will show some nice demos as well, hope to see you there!

Read more about ExpertsLive here: http://www.expertslive.nl

EXPERTSLIVE.5011_email-signature_spreker_ENG_630x180

Speaking at UC Day UK 2016

I’m excited to be speaking at UC Day UK at the National Conference Centre, in Birmingham, 24th October 2016. If you are interested in attending or reading more, visit this link http://www.ucday.uk.

My session will be on Azure Active Directory and how you can perform Premium Management and Protection of Identity and Access with Azure AD, covering solutions like Privileged Identity Management, Identity Protection, Multi-Factor Authentication and Azure AD Connect Health. I will show some nice demos as well, hope to see you there!

JoinSkillriverPremiumIdentityManagementAzureAD

In addition to my session I will during the day be interviewed on The Skype Show (www.theskypeshow.com) about Azure AD and Identity and Access, some of these sessions will go live on Microsoft Channel 9 if logistics permit, or via Skype for Broadcast Meetings or Skype Meetings, and in anyway be recorded and released on Channel 9, Youtube and The Skype Shows website.

image

UC Day will cover technologies like Skype for Business, Exchange, Office 365, Azure and Cloud, and with 25 breakout sessions over 5 tracks, together with expo and sponsors, keynote and closing note. I very much look forward to come there!

How to enable Azure MFA for Online PowerShell Modules that don’t support MFA?

In this blog post I will look into how you can accomplish Azure Multi-Factor Authentication for Admins even though the Online PowerShell Module don’t support it. The key to do this is to implement and use Azure AD Privileged Identity Management, which is an Azure AD Premium P2 / EMS E5 feature.

The Problem

Administration of Online Services with PowerShell can be done with different PowerShell modules or for some scenarios setting up a remote session to the Online Service.  But not all scenarios support Azure MFA natively.

A quick overview of the main modules that DO support Azure MFA today:

All of these above supports Azure MFA as long as you are not passing in a Credential object. There are also more advanced scenarios for programmatic access with Access Token and Certificates that I will not cover here for some of these modules. The main thing is that when you create a Credential object with Get-Credential, and pass that in as a Parameter to the above modules, Azure MFA will not work if the Admin user has been configured to use that. We’ll see some examples later in the blog. Note also that if you have an older version of MSOnline or Aadrm which required the Online Sign-In assistant, these will not work with Azure MFA and you must upgrade to the latest versions.

So what about the modules and scenarios that don’t support Azure MFA. These are mainly Office 365 and Remote PowerShell:

  • Exchange Online Remote PowerShell (Update, a new Exchange Online Remote PowerShell module has now been released, but for a normal PowerShell remoting session this would still not support Azure MFA)
  • Skype for Business Online Remote PowerShell
  • Office 365 Security & Compliance Center Remote PowerShell

In these scenarios you must create a Credential object, and pass that in as a parameter when connecting to the service, thus blocking the use of Azure MFA.

A Security Best Practice for Admins

Today I just don’t find it acceptable for Admin accounts for any Online Service like Azure or Office 365, to not use Multi-Factor Authentication or some other protection mechanism, and just depend on username and password!

In addition to that, as an Organization you have to have control of your identities, employees and admins come and go, I have seen many times that Organizations still have Admin accounts for users that have left the company for a long time ago.

Most Organizations have Directory Synchronization from local Active Directory to Azure AD, making it possible to synchronize your local admin accounts. You then have a choice: Should I use synchronized admin accounts for the Admin Roles in Azure/Office 365? Or should I only create Cloud only admin accounts for this purpose?

My security best practice is to use a combination of both, so that:

  • Synchronized On-Premise Admin Accounts for the most important, permanent and sensitive admin accounts, like Global Admins, Security Admins, Azure Subscription Admins and more. These accounts will be set up to require Azure MFA, as these accounts possibly can connect to On-Premise resources.
  • Cloud Only Admins accounts for Role Based Administration, additional temporary Global Admins or other scenarios for intermittent Azure and Office 365 administration. These accounts will not be set up for Azure MFA, but I use Azure AD Privileged Identity Management to require Azure MFA when activating the role. Some of these accounts also includes service accounts for Directory Synchronization, Intune Connector etc.

The Solution

I have found that the best way to protect both type of Admin accounts is to use the Azure AD Privileged Identity Management and Azure MFA in combination so that:

  • In general all of the permanent Admin Accounts with a few exceptions are required to use Azure MFA. These Admin accounts can use all PowerShell modules that support MFA when connecting.
  • Role-based admins (for example Exchange Admins, Skype for Business Admins,..) are set up to be Temporary/Eligible Admins in Azure AD Privileged Identity Management, which require Azure MFA at activation time. After the admin role is activated, he or she can use the PowerShell modules/remote sessions that don’t support Azure MFA natively.

The downside of this solution is that Azure AD Privileged Identity Management require an Azure AD Premium P2 license or Enterprise Mobility E5 license, which will be Generally Available Sept 15th. Azure MFA are free to use for Admin accounts for Online Services.

How to set it up

In the following steps I will show how to set this up and how it will work. For the purpose for this demo I will work with my demo environment with the tenant name elven.onmicrosoft.com. I have also configured directory synchronization from my on-premise Active Directory, these users will have a UPN suffix of elven.no.

In my environment I have a fictional character called Ola Nordmann. Ola is an Exchange Admin in our Hybrid Exchange environment, and needs permissions to administer Exchange Online in Office 365 both via the management portal and via Exchange Online PowerShell.

Ola has these two accounts now in Azure AD:

image

As per the solution described, I will configure and require Azure MFA for the on-premise admin account, and for the cloud admin account I will use Privileged Identity Management and MFA for role activation.

Configure Multi-Factor Authentication

The easiest way to enable MFA for a user is via the Office 365 Admin portal at https://portal.azure.com. In the user list I find and select the admin user I want to enable MFA for:

image

The Manage multi-factor authentication will take me to the Azure AD multi-factor authentication administration page, where I find and select the admin user:

image

On the right-hand side I select to Enable for the selected user(s):

image

After that I confirm that I want to enable MFA for the user:

image

And get confirmation:

image

Now I see that the status is Enabled, this means that the user needs to log on and configure the authentication method for MFA first:

image

Configure Admin Role

Next, I will give Ola Nordmann the Exchange Administrator role, so that he can administer Exchange Online.

Back in the Office Admin portal I see that the user now has no roles:

image

I select Edit, and choose the Customized administrator and Exchange administrator role, and add the e-mail address of the user:

image

Next, I add the same Exchange administrator role to the Ola Nordmann (Cloud Admin) user:

image

So, at this time, both admin users are Exchange administrators, but only the [email protected] on-premise admin account has been configured for multi-factor authentication.

Log on and activate multi-factor authentication method for admin user

Now I will log on the [email protected] account to https://portal.office.com.

Since this admin account has been configured for MFA, I must set that up now:

image

I need to select an authentication method. In this demo I will use the Microsoft Authenticator App:

image

I select to set up and configure the mobile app:

image

I open up the Microsoft Authenticator app on my phone, and follow the instructions from above. After that I get confirmation that the mobile app has been configured.

image

Now I need to select Contact me to test the authentication:

image

At my phone I get the notification in the App and select verify, and I should be successful. Since I only have set up the mobile app, I also need to add phone number verification in case I lose access to the app. I type my mobile phone number and press next.

image

And in the last step I get an app password to use on some apps, I will not be needing this now for this demo, and click Done:

image

Back in the portal login, I will now be prompted to authenticate with my app:

image

After successfully authenticating I’m logged in to the portal:

image

And since this user has an Exchange administrator role, I can see limited information in the Office 365 admin portal and launch the link to the Exchange admin portal:

image

Try to access Exchange Online PowerShell with MFA enabled admin

First, a quick look back at the multi-factor authentication administration page, where the admin user status has now been updated to Enforced. This happens after the users have been enabled for MFA, and after they have successfully configured their authentication methods. Enforced means that they will now be required to do MFA when authenticating against online services:

image

Let’s try to access Exchange Online PowerShell with this admin user. Instructions for connecting with PowerShell for Office 365 services are detailed here: https://support.office.com/en-us/article/Managing-Office-365-and-Exchange-Online-with-Windows-PowerShell-06a743bb-ceb6-49a9-a61d-db4ffdf54fa6?ui=en-US&rs=en-US&ad=US

I launch a PowerShell window and get a Credential object:

image

After that I try to create a remote session with that credential:

image

As expected this will fail, as multi-factor auhtentication is required for the [email protected] account.

In the next part we will look at the other cloud admin user and configure the workaround using Azure AD Privileged Identity Management.

Configure Azure AD Privileged Identity Management for Exchange administrators

At this next step I log in as a Global Administrator, and if I haven’t already added the Privileged Identity Management solution, I can add it from the Azure Marketplace:

image

The first Global Administrator that set up Privileged Identity Management will added to the Security Administrator and Privileged Role Administrator Roles. After that we can manage the privileged roles. If you have previously added the solution, you will have to activate your Privileged Role administrator first.

image

When I select the Exchange Administrator role, I can see both admin accounts for my Ola admin user. These roles are assigned on a permanent basis:

image

Azure AD Privileged Identity Management will let me assign and change admin roles from permanent to eligible for temporary activation. I will do this for the [email protected] cloud admin account:

image

After I click Make eligible, the admin account are removed from permanent role and are now listed as Eligible:

image

Lets click on the Settings button for the Exchange Administrator role. At settings I can set the activation duration, email notifications, ticketing and fore some roles I can select whether to require multi-factor authentication for activation:

image

These settings can also be set as default for all roles:

image

At this point my cloud admin [email protected] has been removed as a permanent Exchange Administrator, and will require activation before he will be temporarily activated as an Exchange Administrator for one hour duration.

Log on as admin user without activation

When I log in to the Office 365 portal with the [email protected], I will see that this user is just a normal user with no admin links, This is expected as the user hasn’t activated the Exchange Administrator role.

image

Activate the Exchange Administrator Role

Next I go to the Azure portal at https://portal.azure.com still logged on as [email protected]. First I need to add the Privileged Identity Management solution:

image

After adding the solution, I can request activation for the roles I’m eligible for, in this case Exchange Administrator:

image

When requesting activation I need to verify my identity first:

image

If my account hasn’t already been set up for multi-factor authentication, it will be guided to do that now:

image

After configuring and verifying multi-factor authentication, I can now activate my Exchange Administrator role and provide a reason:

image

After successful activation I can verify the duration I will be activated for:

image

Log on to the Office 365 Portal and Exchange Admin Center after activation

After activation, I should log off and back on with my activated admin role account, and this time I will see the Exchange Admin portal:

image

Log on to Exchange Online PowerShell after activation

And finally, I can start an Exchange Online PowerShell Session with my activated account. First I get my credential:

image

Then I can create the remote Exchange Online session and import it to PowerShell:

image

And finally just try out some Exchange Online administration successfully:

image

Summary

At the end of this long blog post, we can summarize that we have accomplished the solution of adding Azure Multi-Factor Authentication for scenarios where the PowerShell Module or Remoting Session does not natively support it. This is made possible by using Azure AD Privileged Identity Management, and by making some role administrators eligible and require MFA when activating. This way they have verified their identity before they connect with the Credential object.

This is just one scenario where both Azure AD MFA and Privileged Identity Management can be used together for increased security and reduce the attack surface of having vulnerable permanent administrator accounts and roles.

I hope this blog post have been informative and helpful, please reach out or comment if you want to know more or have any questions.