Tag Archives: PowerShell

New Exchange Online PowerShell v2

When using PowerShell with Exchange Online you can use the ‘good old traditional’ way to connect to Exchange Online:

$ExCred = Get-Credential 
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $ExCred -Authentication Basic -AllowRedirection
Import-PSSession $Session

This is not a recommended way to connect to Exchange Online using your tenant admin account, it uses basic authentication (will be decommissioned in 2021) and MFA (number one prerequisite for tenant admin security!) is not possible.

The second option is the Exchange Online Remote PowerShell Module which you can download from the Exchange Online Admin Center (use Internet Explorer for this download!) as shown in the following screenshot:

Exchange Online PowerShell Module

This is a separate PowerShell module you can start and use the Connect-EXOPSSession command to connect to Exchange Online. This PowerShell module users Modern Authentication and supports Multi-Factor Authentication.

The latest (and newest) option is the Exchange Online PowerShell V2 module. This module works far more efficient with large datasets than the previous PowerShell modules for Exchange Online. It also supports Modern Authentication and Multi-Factor Authentication.

To install the Exchange Online PowerShell V2 module you first have to install the PowerShellGet module using the Install-Module PowershellGet command:

Install-Module PowershellGet

Followed by the Install-Module -Name ExchangeOnlineManagement command:

Install-Module ExchangeOnlineManagement

When installed you can use the Connect-ExchangeOnline command to connect to Exchange Online. When MFA for your admin account is configured it will automatically use it:

Connect-ExchangeOnline

The differences between V1 and V2 are clearly visible in the commands. All V2 commands contain EXO, like:

  • Get-Mailbox vs Get-EXOMailbox
  • Get-Recipient vs Get-EXORecipient
  • Get-MailboxStatistics vs Get-EXOMailboxStatistics
  • Get-CASMailbox vs Get-EXOCASMailbox

This means that all scripts you have written for use with Exchange Online need to be changed to reflect the V2 commands.

For a complete overview you can use the Get-Command *EXO* to retrieve all PowerShell commands that contain EXO (still very limited 🙂 ):

Get-Command EXO

The Exchange Online PowerShell V2 module is still in preview, the current version is 0.3582.0 which you can check using the Get-Module ExchangeOnlineManagement command:

Get-Module ExchangeOnlineManagement

The Exchange Online PowerShell v2 module is a work in progress, but it the future of PowerShell in Exchange Online, so you should keep an eye on this development.

More Information

Use the Exchange Online PowerShell V2 module – https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/exchange-online-powershell-v2/exchange-online-powershell-v2?view=exchange-ps

Install-Module MSOnline fails with unable to download from URI

When installing the MSOnline module using the Install-Module MSOnline command in PowerShell it fails with a cryptic error like:

WARNING: Unable to download from URI ‘https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409’ to ”.
WARNING: Unable to download the list of available providers. Check your internet connection.
PackageManagement\Install-PackageProvider : No match was found for the specified search criteria for the provider ‘NuGet’. The package provider requires ‘PackageManagement’ and ‘Provider’ tags. Please check if the specified package has the tags.

And

WARNING: Unable to download from URI ‘https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409’ to ”.
WARNING: Unable to download the list of available providers. Check your internet connection.
PackageManagement\Get-PackageProvider : Unable to find package provider ‘NuGet’. It may not be imported yet. Try ‘Get-PackageProvider -ListAvailable’.
Install-Module : NuGet provider is required to interact with NuGet-based repositories. Please ensure that ‘2.8.5.201’ or newer version of NuGet provider is installed.

As shown in the following screenshot:

Install-PackageProvider

It turns out that this is a TLS issue, PowerShell does not use TLS 1.2 by default, while Microsoft requires TLS 1.2 from clients. To set TLS 1.2 usage for PowerShell, you can use the following command:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Now if you try again, it will install the MSOnline module:

Install-Module MSOnline

This is a per session setting, if you want to enable it for all sessions, add the previous command to the Microsoft.PowerShell_profile.ps1 and Microsoft.PowerShellISE_profile.ps1 profiles (use Notepad $Profile for this.

More information

Azure ActiveDirectory (MSOnline) – https://docs.microsoft.com/en-us/powershell/azure/active-directory/install-msonlinev1?view=azureadps-1.0

Block creation of Office 365 Groups

I’m an old school IT guy, in my world provisioning is done via the IT department or via a provisioning tool. What I don’t want is that regular users create all kinds of objects in my environment, whether it be Active Directory, Azure Active Directory or Office 365.

In Office 365 everything is different, multiple services (Outlook, Teams, Planner, SharePoint, PowerBI and others) are using Office 365 Groups under the hood. So, when users create a new plan in Planner or a new team in Teams, they also create an Office 365 Group in Azure Active Directory.

I’m currently working in a 12,000-user environment, and the last thing I want to happen is 12,000 users randomly creating all kinds of groups, ending up in a total mess where nobody can find information and where it is impossible to delete anything without hurting other people.

The solution for this is to assign the creation of new Office 365 to a security group in Azure Active Directory (this can be a cloud object or a synchronized object). To create a new security group in Azure Active Directory you can use the following PowerShell command:

New-AzureADGroup -DisplayName "O365 Group Creators" -SecurityEnabled:$True -MailEnabled:$False -MailNickName "Nothing"

New-AzureADGroup

Note. It is also possible to create a security group in the Azure AD Portal.

The next step is to assign the permission to create Office 365 Groups to this new security group. This can only be achieved using PowerShell and the Azure AD Preview Module, using the following script:

$GroupName = "O365 Group Creators"
$AllowGroupCreation = "False"
Connect-AzureAD
$settingsObjectID = (Get-AzureADDirectorySetting | Where-object -Property Displayname -Value "Group.Unified" -EQ).id
if(!$settingsObjectID)
{
  $template = Get-AzureADDirectorySettingTemplate | Where-object {$_.displayname -eq "group.unified"}
  $settingsCopy = $template.CreateDirectorySetting()
  New-AzureADDirectorySetting -DirectorySetting $settingsCopy
  $settingsObjectID = (Get-AzureADDirectorySetting | Where-object -Property Displayname -Value "Group.Unified" -EQ).id
}
$settingsCopy = Get-AzureADDirectorySetting -Id $settingsObjectID
$settingsCopy["EnableGroupCreation"] = $AllowGroupCreation
if($GroupName)
{
  $settingsCopy["GroupCreationAllowedGroupId"] = (Get-AzureADGroup -SearchString $GroupName).objectid
}
Set-AzureADDirectorySetting -Id $settingsObjectID -DirectorySetting $settingsCopy
(Get-AzureADDirectorySetting -Id $settingsObjectID).Values

When you run this script, you will see a similar output:

GroupCreators

The first box corresponds to the objectID of the security group we’ve created in the first step, just compare with the ObjectID shown in the first screenshot.

The second box shows $false for the EnableGroupCreation property, indicating no other groups are allowed to create Office 365 Groups.

All members of the security group we just created are allowed to create Office 365 groups. There are some exceptions though, Exchange admins, SharePoint admins, Teams admins and User Management admins are by default allowed to create Office 365 groups as well, but typically these are not regular users.

This way you can control who is able to create Office 365 Groups in your environment, and make sure group creation doesn’t explode in your tenant.

More information

Prepopulate mobile phone for multi-factor authentication

I am working with a customer where we want to enable multi-factor authentication for their users as a measure to secure their environment. But when you enable MFA and a user logs on for the first time, the user has to enter his mobile phone number, even if the mobile phone number is populated in on-premises Active Directory and synchronized to Azure Active Directory (which is default).

additional security verification

When you check the user account in the Azure AD portal, you can see that the mobile phone number is synchronized, but the authentication phone number is empty.

authentication contact info

This is not a desired solution, if a user can set a new mobile phone during logon, a malicious user can do this as well. A typical user will logon shortly after the MFA is set, but especially when doing bulk changes this might not be the case. And when a user account that is MFA enabled, but hasn’t set the authentication phone property is compromised you’re screwed.

Out of the box there’s no easy way to prepopulate the authentication phone number. The authentication phone number is not store in on-premises Active Directory, it’s an Azure AD property. The property to control the strong authentication is called StrongAuthenticationMethods and you can set this using PowerShell. When you set this, the authentication phone number is still prepopulated, but when the mobile phone number is synchronized, this is used in the first place.

To set this StrongAuthenticationMethods property you can use the following PowerShell commands:

Connect MsolService 
$UserPrincipalName = "j.brown@exchangelabs.nl"
$SMS = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationMethod
$SMS.IsDefault = $true
$SMS.MethodType = "OneWaySMS"
$Phone = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationMethod
$Phone.IsDefault = $false
$Phone.MethodType = "TwoWayVoiceMobile"
$PrePopulate = @($SMS, $Phone)
Set-MsolUser -UserPrincipalName $UserPrincipalName -StrongAuthenticationMethods $PrePopulate

Now when the user logs on for the first time with MFA enabled, he’s presented the enter code dialog box, without having to enter a mobile number first.

we texted your phone

If you do this, and the mobile phone number is not set in on-premises Active Directory, MFA will still try to use the mobile phone number, but nothing will happen as shown in the following screenshot:

we are having trouble verifying your account

Since there’s no mobile phone number to use, and no option to add this anymore directly by the user you’re stuck here (until the mobile phone number is added to on-premises Active Directory of course).

Note. If you want to enable MFA using PowerShell, you can use the following commands (and maybe combine them with the commands mentioned earlier):

$Strong = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$Strong.RelyingParty = "*"
$Strong.State = "Enabled"
$MFA = @($Strong)
Set-MsolUser -UserPrincipalName j.smith@exchangelabs.nl -StrongAuthenticationRequirements $MFA

More information

Exchange 2019 on Windows Server Core disk management

When installing an Exchange 2019 Edge Transport server on Windows 2019 Server core I realized there’s no disk management MMC snap-in, so all disk configuration needs to be done using PowerShell.

For this blogpost I added a 20GB disk to my Windows 2019 Server Core server which I want to use as a D:\ drive for my SMTP queue.

You can use the Get-Disk command to retrieve the server’s disk configuration, and you can pipe this disk object into the Initialize-Disk command to bring it online and assign a new partition:

Get-Disk –Number 1 | Initialize-Disk –PartitionStyle GPT New-Partition –DiskNumber 1 –UseMaximumSize

Initialize-Disk

By default, Windows installs on drive C:\ and the DVD is mounted as drive D:\. You can use the Get-WmiObject and the Set-WmiInstance commands to assign it a different drive letter, for example drive Z:\

Get-WmiObject -Class Win32_volume -Filter ‘DriveType=5′ | Select -First 1 | Set-WmiInstance -Arguments @{DriveLetter=’Z:’}

The next step is to assign drive letter D:\ to the newly added disk:

Add-PartitionAccessPath -DiskNumber 1 -PartitionNumber 2 –AccessPath “D:\”

And finally format it using NTFS file system and a block size of 64KB:

Get-Partition –Disknumber 1 –PartitionNumber 2 | Format-Volume –FileSystem NTFS –NewFileSystemLabel “Queue” -AllocationUnitSize 65536 –Confirm:$false

format-disk

Now you can continue with the standard installation procedure for an Exchange 2019 Edge Transport server (which does not differ from an Exchange 2013 or Exchange 2016 Edge Transport server)