New reports layout and new Forms report in the Microsoft 365 Admin Center

While doing some fact-checking against the reports page within the Microsoft 365 Admin Center earlier today, I noticed that we now have a new layout for it, as showcased below:

Front and center, we have the Active users report in Graph form, showing activities across the different workloads for the past 30 days. While you can change the reporting interval using the dropdown in the top right corner, if you want to perform any other modifications or export the data, you should head over to the details page. Incidentally, there seems to be no way for doing so for the Active users report, apart from having to click on the View more button under any of the other report entries presented on the page and using the “switcher” there.

Speaking of which, the other tiles correspond to the following reports:

  • Microsoft 365 active users (per service)
  • Microsoft 365 App usage
  • Email activity
  • Microsoft Teams activity
  • OneDrive files
  • SharePoint files
  • Office activations
  • Yammer activity
  • Forms activity
  • Skype for Business activity

Lastly, a link to the Microsoft 365 usage analytics solution for PowerBI is presented.

Clicking the View more button under any of the above mentioned entries will take you to the corresponding “standalone” report page, which has the old look and feel. Nothing is changed in terms of functionality here it seems, so you can get all the familiar controls, including the “switcher” on top.

In other news, a new Microsoft Forms activity report has been added, which as the name suggests covers activities in Forms. The chart on top of the report page will show the number of users that have created or responded to a Form, while the activity tab should cover the total number of created and filled in forms, including those by anonymous users. The data seems to be a bit off though, as the table representation doesn’t match the graph above. For example, while I do have several forms created over the past few months, mostly for collecting questions for our V2 Exchange PowerShell webinars, my user is shown with last active date of 18 December 2019, and a count of zero for the number of forms created field.

On the other hand, the graph representation seems to match the actual activities performed in Forms, including the number of responses by anonymous users. Since I haven’t seen any official announcement for this report yet, and there doesn’t seem to be a matching Graph API endpoint for it either, one can assume that this is still in beta/preview, so over time these issues should be addressed.

Posted in Microsoft 365 | Leave a comment

Preset security policies for Exchange Online Protection

With the growth of functionality across the different Office 365 workloads, it is becoming increasingly difficult for organizations to keep up with changes, enforce configurations across multiple tenants, or even stick to the “best practices”. Over the past few months, Microsoft has launched several initiatives that can help with such scenarios, like the Microsoft 365 DSC initiative, the Office 365 ATP Recommended Configuration Analyzer (ORCA) tool, and more recently, few preset security policies for EOP and Office 365 ATP. In this article, we will take the latter for a quick spin.

As the name suggests, the preset security policies represent a template of sorts, configured to match Microsoft’s recommendations. Currently, two presets are available, namely Standard protection and Strict protection. One can also think of them as “baseline policies”. As such, they are not configurable, as in you cannot customize them, even if some minor change is needed. The only thing you can modify is the set of recipients to which a given preset will apply, and in turn the set of individual policies. Speaking of which, the policies included in each preset are:

  • Anti-spam policy
  • Anti-malware policy
  • Anti-phishing policy (either EOP or ATP one, depending on the subscription you have)
  • ATP Safe link policy
  • ATP Safe attachments policy

Note that the anti-spam policy is a single entry representing settings across the content and connection filter policies.

Now that we know what preset policies are, how do we go about assigning those, and more importantly, seeing what exactly they do? Both the old Security and Compliance Center and new (and still almost useless) Microsoft 365 Security Center expose the preset policies functionality. In the SCC, you can find them under Threat protection > Policy > Preset security policies, or using the direct link. In the mess that is the Security Center, you need to first go to the Policies entry on the left nav menu, then click any entry under the Threat protection section, for example Anti-spam, then once the corresponding settings load up in a new tab, hit the Threat policies entry on top, and here you will finally find Preset security policies. Or you can just use the direct link:

Under the Preset security policies page, you will find a short description of the feature, along with a link to the documentation. The rest of the page is taken by the list of currently assigned policies, split between the two policy types (Standard on the left and Strict on the right). To create a new assignment for a given policy, one can use the Edit button under the corresponding policy. Hitting the button will bring forth a new-style wizard-type interface with just three sections, as showcased below. All that you need to (or can) configure here is the list of users to which the policy will apply to, by selecting one of the conditions or exceptions you’re probably familiar with from assigning other types of EOP/ATP policies. Those are split between the EOP protections apply to and ATP protections apply to pages, while the last page gives you a quick summary.

As shown on the screenshots, you can target the different sets of policies to different groups of users. You can also configure multiple preset policies (as in both the Standard and the Strict one) to apply to the same set of users, either intentionally or by mistake. When multiple presets are applied to the same user, the Strict preset has the highest precedence, followed by the Standard preset, custom configured policies and lastly, the default policies.

The other controls exposed in the UI include the Enabled/Disabled toggle, which as the name suggest serves to quickly toggle the preset policies on or off. Lastly, a Refresh button is presented, as in some cases the UI doesn’t immediately list all newly configured conditions/exceptions to which a given preset applies. Hitting said button or refreshing the page should take care of that though.

Nowhere in the UI can you actually see which individual policy settings are changed by the presets you assigned above. To get this information, you’ll have to review the Recommended settings for EOP and Office 365 ATP security article, which presents you with a breakdown of each individual setting, along with its corresponding values when using the Standard or Strict policy presets. As to verifying whether the policy settings have been applied successfully to the (groups of) users in question, Microsoft recommends checking the end result. That is, check where a message marked as spam ends up, and same for bulk messages. This might sound fishy at first, but a quick look at the “recommended settings” article linked above reveals that the two presets differ in only a handful of settings, with the SpamAction and BulkAction in particular being the easiest one to check against. Other than that, the most noticeable difference is in the Outbound spam setting values, however those might not yet apply according to a recent comment over at GitHub.

Lastly, you can manage the preset policies assignment via the set of *-ATPProtectionPolicyRule PowerShell cmdlets:

  • Disable-ATPProtectionPolicyRule
  • Enable-ATPProtectionPolicyRule
  • Get-ATPProtectionPolicyRule
  • New-ATPProtectionPolicyRule
  • Remove-ATPProtectionPolicyRule
  • Set-ATPProtectionPolicyRule

That concludes our short overview of the recently introduced Preset security policies for Exchange Online Protection. I’ll make sure to update the article as additional presets are released or their functionality is expanded to cover additional settings.

Posted in Exchange Online, Microsoft 365, Office 365 | Leave a comment

Reporting on group membership for Azure AD devices

Now that we have device-based licensing for Office available to enterprise customers as well, adding device objects to Azure AD groups will become more common. The need to report on group membership for device objects will also arise. Neither the Azure AD blade nor PowerShell provide an easy option to do this, and while you can certainly enumerate all groups and their members via the Azure AD cmdlets (note that the old MSOnline module does not recognize devices as valid members for groups), this approach is not optimal.

Luckily, the Graph API gives us a better method, namely calling the memberOf endpoint, which is also supported for Device objects. We don’t yet however have a matching Azure AD PowerShell cmdlet (Get-AzureADUserMembership only covers user objects as the name suggestes), so if you want to do this via PowerShell you have to call the Graph endpoints directly. And since I’ve been posting a lot of proof-of-concept scripts around the use of Graph API lately, I figured I’d do yet another one for this scenario.

In a nutshell, all we have to do is fetch the list of device objects in the tenant by calling the devices endpoint, then loop over each device and query the memberOf, or the analogous transitiveMemberOf endpoint. And lastly, export the result to CSV file. Of course some additional details would be needed in order to obtain a token first, but I’ve covered the process in multiple articles already, so I’ll just skip the steps this time around.

You can find the sample script over at my GitHub repo. As usual, it lacks robust error checking, anti-throttling controls and so on, being a proof-of-concept code and all. It also fetches a minimal set of properties for each device, which you might want to expand on. I’d recommend always including at least one unique-valued property, such as the ObjectId. Same goes for the actual Groups returned by the transitiveMemberOf query, while of course it’s much easier to use display names in the output, you might end up with duplicate values and ambiguous results. Of course, you can always modify the code to export additional properties, for example by adding a new line for each device/group combo and dumping additional information about the group so that you don’t have to do additional queries later on (for example, is this a Security group, or an M365 group, is it mail-enabled, is it security-enabled, etc.).

It goes without saying that you should test this code before running it in production environments. While I’ve added the necessary bits to handle large number of devices, I only have a dozen or so in my tenants so I cannot possibly test for all scenarios. And again, minimum error handling is added to the code, so you might want to expand on that part as well. Let me know if you run into any issues.

Posted in Azure AD, Graph API, Microsoft 365, Office 365, PowerShell | Leave a comment

Enterprise customers can now get device-based licensing for Office

Or as Microsoft calls it: Device-based licensing for Microsoft 365 Apps for enterprise

Back at Ignite 2019, Microsoft announced a preview for the new device-based licensing for Office desktop apps (now Microsoft 365 Apps). The planned GA date was “summer 2020”, and it seems all went according to plan as the feature is now released publicly. The list of requirements is as follows:

  • The feature is available only for certain EDU and commercial customers.
  • As commercial customer, you must have an Enterprise Agreement/Enterprise Agreement Subscription, and the SKU is Microsoft 365 Apps for enterprise (device).
  • As EDU customer, you can get the Microsoft 365 Apps for Education (device) SKU through Enrollment for Education Solutions.
  • The device must be running Window 10.
  • Only version 1803 or later is supported (the LTSC version has the same requirement).
  • Version 1907 or above of the Office suite (Microsoft 365 Apps) is required.
  • The device must be Azure AD joined or Azure AD hybrid joined and must be joined to Azure AD beforehand.
  • You cannot directly license a given device, you must add them to a group first.
  • The group containing the devices objects must be created beforehand via the Azure AD blade, as the Microsoft 365 admin portal is still not updated to recognize device objects. You can also use PowerShell or the Graph API.
  • The group must be of type “security”, or a distribution group. Office 365 groups or mail-enabled security groups are supported.
  • If using a security group, it can have dynamic membership (device condition). Dynamic distribution groups are not supported, as they are not recognized by Azure AD.
  • The group can be synced from on-premises AD, the above requirements must be met though.
  • A license must be assigned to the group via the Microsoft 365 Admin center (Billing -> Licenses -> click the Microsoft 365 Apps for enterprise (device) license -> Assign licenses -> select the group created as per the previous steps. (You can probably use the Azure AD blade to assign the license to the group as well, but since my test tenant doesn’t qualify for EA, I cannot test this. Do note that Microsoft recommends using the M365 portal only).
  • The Office install must be configured for device-based licensing, either via the ODT, GPOs, or reg keys directly.

Additional details can be found in the documentation here and here.

Posted in Azure AD, Microsoft 365, Office 365 | 1 Comment

Toggle Azure AD Security Defaults on or off programmatically

Continuing our exploration of the different policies objects exposed under the /policies Graph API endpoint, in this article we will discuss how to get the current state of the Security defaults feature, and change it as needed. But first, a word or two about Security defaults.

The Security defaults feature is basically a set of pre-configured settings, intended to beef up the security of your organization. Apart from disabling basic authentication and forcing MFA for admins, it includes things such as mandatory MFA registration for users. While most enterprise customers have probably already configured all these settings, or are planning to, the biggest benefit of the feature is that it’s made available for free for all tenants, even those that are not licensed to use services such as Azure AD Identity Protection. The downside is that it lacks the customizability of the individual features, especially when compared to Conditional Access policies, and is basically an “all or nothing” toggle.

Because of the “all or nothing” approach, it’s not that uncommon for Security defaults to interfere with the normal work of users and/or admins, and there have been multiple issues reported on the different technical communities, all of which caused by the feature. While you can check the status of the feature and toggle it from the Azure AD blade, this UI-based approach is not always applicable. So, it might be useful if you have a way to programmatically report on or toggle Security defaults, which is what the /policies/identitySecurityDefaultsEnforcementPolicy endpoint enables.

Here’s how to report on the current status of the feature (note that the application you plan to use must have the Policy.Read.All and Policy.ReadWrite.ConditionalAccess scopes granted):

$tenantID = "" #your tenantID or tenant root domain
$appID = "12345678-1234-1234-1234-1234567890AB" #the GUID of your app. For best result, use app with Policy.Read.All and Policy.ReadWrite.ConditionalAccess scopes granted
$client_secret = "XXXXXXXXXXXXXXXxxxx" #client secret for the app

$body = @{
client_id     = $AppId
scope         = ""
client_secret = $client_secret
grant_type    = "client_credentials"

$authenticationResult = Invoke-WebRequest -Method Post -Uri "$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body -ErrorAction Stop
$token = ($authenticationResult.Content | ConvertFrom-Json).access_token
$authHeader = @{'Authorization'="Bearer $token"}

$res = Invoke-WebRequest -Headers $AuthHeader -Uri ""
$result = ($res.Content | ConvertFrom-Json)

@odata.context :$metadata#policies/identitySecurityDefaultsEnforcementPolicy/$entity
id             : 00000000-0000-0000-0000-000000000005
displayName    : Security Defaults
description    : Security defaults is a set of basic identity security mechanisms recommended by Microsoft. When enabled, these recommendations will be automatically enforced in your organization. Administrators and users will be better protected from common identity related attacks.
isEnabled      : False

In this case, the feature has been toggled Off, or wasn’t enabled at all because of already existing CA policies.  To toggle it On, we can use the following PATCH request (make sure that no CA policies that interfere with Security defaults are enabled though):

$body = (@{"isEnabled"="true"} | ConvertTo-Json)
$authHeader = @{'Authorization'="Bearer $token";"Content-Type" = "application/json"}
$res = Invoke-WebRequest -Headers $AuthHeader -Uri "" -Method Patch -Body $body

And that’s pretty much all there is to it. Re-runing the GET request now should show the status of the isEnabled property is set to True, thus Security defaults have been enabled.

Posted in Azure AD, Graph API, Microsoft 365, Office 365, PowerShell | 1 Comment