30 October 2018

Enable Office365 MFA per user or all users - Search for users with MFA disabled

Enabling all users for MFA is relatively easy with PowerShell, and how to's are found all over the web.
But enabling MFA for one user is a bit more difficult.
Here's how to do it:

Enable MFA per user
#Create the StrongAuthenticationRequirement object and insert required settings
$mf= New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$mf.RelyingParty = "*"
$mfa = @($mf)
#Enable MFA for a user
Set-MsolUser -UserPrincipalName userprinciplename@domain.com -StrongAuthenticationRequirements $mfa


#Enable MFA for all users (use with CAUTION!)
Get-MsolUser -All | Set-MsolUser -StrongAuthenticationRequirements $mfa

Check the settings
$User = Get-msoluser -UserPrincipalName 'user@domain.com' | Select-Object -ExpandProperty StrongAuthenticationRequirements
$User.State

#List All users and MFA status :            
Connect-MsolService            
            
$Result=@()             
$users = Get-MsolUser -All            
$users | ForEach-Object {            
$user = $_            
if ($user.StrongAuthenticationRequirements.State -ne $null){            
$mfaStatus = $user.StrongAuthenticationRequirements.State            
}else{            
$mfaStatus = "Disabled" }            
               
$Result += New-Object PSObject -property @{             
UserName = $user.DisplayName            
UserPrincipalName = $user.UserPrincipalName            
MFAStatus = $mfaStatus            
}            
}            
$Result | Select UserName,UserPrincipalName,MFAStatus            
            
#List only MFA enabled users :            
Connect-MsolService            
            
$Result=@()             
$users = Get-MsolUser -All            
$users | ForEach-Object {            
$user = $_            
if ($user.StrongAuthenticationRequirements.State -ne $null){            
$mfaStatus = $user.StrongAuthenticationRequirements.State            
}else{            
$mfaStatus = "Disabled" }            
               
$Result += New-Object PSObject -property @{             
UserName = $user.DisplayName            
UserPrincipalName = $user.UserPrincipalName            
MFAStatus = $mfaStatus            
}            
}             
$Result | Where-Object {$_.MFAStatus -ne "Disabled"}            
            
#List only MFA disabled users :            
Connect-MsolService            
            
$Result=@()             
$users = Get-MsolUser -All            
$users | ForEach-Object {            
$user = $_            
if ($user.StrongAuthenticationRequirements.State -ne $null){            
$mfaStatus = $user.StrongAuthenticationRequirements.State            
}else{            
$mfaStatus = "Disabled" }            
               
$Result += New-Object PSObject -property @{             
UserName = $user.DisplayName            
UserPrincipalName = $user.UserPrincipalName            
MFAStatus = $mfaStatus            
}            
}            
$Result | Where-Object {$_.MFAStatus -eq "Disabled"}            
            
#Export 365 users MFA status to CSV file :            
Connect-MsolService            
            
$Result=@()             
$users = Get-MsolUser -All            
$users | ForEach-Object {            
$user = $_            
if ($user.StrongAuthenticationRequirements.State -ne $null){            
$mfaStatus = $user.StrongAuthenticationRequirements.State            
}else{            
$mfaStatus = "Disabled" }            
               
$Result += New-Object PSObject -property @{             
UserName = $user.DisplayName            
UserPrincipalName = $user.UserPrincipalName            
MFAStatus = $mfaStatus            
}            
}            
$Result | Select UserName,UserPrincipalName,MFAStatus | Export-CSV "C:\Temp\O365-Users-MFA-Status.csv" -NoTypeInformation -Encoding UTF8            
            
#Create the StrongAuthenticationRequirement object and insert required settings            
$mf= New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement            
$mf.RelyingParty = "*"            
$mfa = @($mf)            
            
#Enable all disabled users for MFA :            
Connect-MsolService            
            
$Result=@()             
$users = Get-MsolUser -All            
$users | ForEach-Object {            
$user = $_            
if ($user.StrongAuthenticationRequirements.State -ne $null){            
$mfaStatus = $user.StrongAuthenticationRequirements.State            
}else{            
$mfaStatus = "Disabled" }            
               
$Result += New-Object PSObject -property @{             
UserName = $user.DisplayName            
UserPrincipalName = $user.UserPrincipalName            
MFAStatus = $mfaStatus            
}            
}            
$Result | Where-Object {$_.MFAStatus -eq "Disabled"} | Set-MsolUser -StrongAuthenticationRequirements $mfa

Identify users who have registered for MFA and count the number of users.
$Registered = Get-MsolUser -All | where {$_.StrongAuthenticationMethods -ne $null} | Select-Object -Property UserPrincipalName            
$registered            
$registered.count

Identify users who have not registered for MFA and count the number of users.
$NotRegistered = Get-MsolUser -All | where {$_.StrongAuthenticationMethods.Count -eq 0} | Select-Object -Property UserPrincipalName            
$NotRegistered            
$NotRegistered.count

Bulk enable for multiple users in csv file
Enable for multiple users
function Set-MFAUsers {            
    param (            
        [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]            
        [ValidateScript( {Test-Path $_})]              
        [Alias('FullName')]            
        [String] $Path,            
                    
        [ValidateSet('Enabled','Enforced')]            
        [String] $State = 'Enabled'            
    )            
            
    # Set MFA object            
    $MFASetting = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement -Property @{            
        RelyingParty = "*"            
        State        = $State            
    }            
                
    # Get user list            
    $Users = Get-Content -Path $Path -ReadCount -1            
            
    foreach ($user in $users)             
    {            
         $SetUser = @{            
            UserPrincipalName                = $user            
            StrongAuthenticationRequirements = $MFASetting             
            ErrorAction                      = 'Stop'              
        }            
            
        Try {            
            # Set MFA            
            Set-MsolUser @SetUser            
                        
            # Post Check            
            $ThisUser = Get-msoluser -UserPrincipalName $User |             
                Select-Object -ExpandProperty StrongAuthenticationRequirements            
            
            if ($ThisUser.State -eq $SetUser.StrongAuthenticationRequirements.State) {            
                Write-Host "[SUCCESS] UPN: $user" -ForegroundColor Green            
            }            
            else {            
                Write-Host "[FAILED ] UPN: $user" -ForegroundColor Red            
            }            
        }            
        Catch {            
             Write-Warning -Message $_.Exception.Message            
        }               
    }             
}            
            
Get-ChildItem C:\temp\MFA_Users.txt | Set-MFAUsers -State Enforced

19 October 2018

Exchange 2013 and 2016 - Create Edge subscription

I keep forgetting this:

This is for Exchange 2010, 2013 and 2016 and probaly 2019 but I didn't check this.

Create a new subscription file on the Edge server:
New-EdgeSubscription -FileName C:\Temp\Servername-Edge.xml

Copy the file to a mailbox server and import using this command:
New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "C:\Temp\Servername-Edge.xml" -Encoding Byte -ReadCount 0)) -Site "Sitename"

451 4.4.0 Primary target IP address responded with: 454 4.7.0 Temporary authentication failure - Exchange Edge

The error doesn't suggest anything that could point you to a solution.
In my case it wasn't the KB article found here.

Turned out to be a certificate Service assignment that got lost.

The error in the Eventviewer was:

EventID: 12023
Level: Warning
Task Category: Transportservice
Source: MSExchangeFrontEndTransport
Microsoft Exchange could not load the certificate with thumbprint of BAE49XX5021785XX4433FXXA78XX434CXXBD4EXX from the personal store on the local computer. This certificate was configured for authentication with other Exchange servers. Mail flow to other Exchange servers could be affected by this error. If the certificate with this thumbprint still exists in the personal store, run Enable-ExchangeCertificate BAE49XX5021785XX4433FXXA78XX434CXXBD4EXX -Services SMTP to resolve the issue. If the certificate does not exist in the personal store, restore it from backup by using the Import-ExchangeCertificate cmdlet, or create a new certificate for the FQDN or the server enabled for SMTP by running the following command: New-ExchangeCertificate -DomainName serverfqdn -Services SMTP. Meanwhile, the certificate with thumbprint XX728XXD9AD2D55XXE9F9D4BEXX8949AE4DXXCBA is being used.

When running the command:
Get-ExchangeCertificate

Thumbprint                                Services   Subject
----------                                --------   -------
499A246DF957FDF438CD9C7BF5DB070E326B0AF9  ...W...    CN=sr-XXXXX.domain.lan, O=Trend Micro ScanMail for Microsoft Ex...
4272892D9AD2D557DE9F9D4BEB98949AE4D8CCBA  .......    CN=sr-XXXXX.domain.lan
065470FCE311211810679A92A4A2F67708E29398  .......    CN=SkypeforBusiness-OWA
DA9D8609DED5198F1AEEE96E3CCE33ED7323DA5E  IP.WS..    CN=service0.domain.lan
ECB0F4D6FE4BCA7B6DAB79C96F491222F845B3B9  ....S..    CN=service1.domain.nl, O=domain N.V., L=City, S=State, C=NL
E40C46317EE13A419C3B41334EFEA37EFC7E5813  ....S..    CN=sr-XXXXX
2B55508050B8C4269D4DA3EE5C97B346AEAFDF7C  .......    CN=WMSvc-SR-XXXXX
93EEEB92883AB769FD22226B8B78DAB4C60EABD0  ....S..    CN=Microsoft Exchange Server Auth Certificate


Enable-ExchangeCertificate DA9D8609DED5198F1AEEE96E3CCE33ED7323DA5E -Services SMTP

Confirm
Overwrite the existing default SMTP certificate?

Current certificate: 'BAE49EF5021785CA4433F25A7800434CA4BD4E6E' (expires 21-11-2017 13:51:22)
Replace it with certificate: 'DA9D8609DED5198F1AEEE96E3CCE33ED7323DA5E' (expires 26-9-2020 14:12:44)
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [?] Help (default is "Y"): y
A special Rpc error occurs on server SR-XXXXX: The internal transport certificate for the local server was damaged or m
issing in Active Directory. The problem has been fixed. However, if you have existing Edge Subscriptions, you must subs
cribe all Edge Transport servers again by using the New-EdgeSubscription cmdlet in the Shell.
    + CategoryInfo          : ObjectNotFound: (:) [Enable-ExchangeCertificate], InvalidOperationException
    + FullyQualifiedErrorId : [Server=SR-XXXXX,RequestId=30ee7bbb-899d-4cb0-b4e2-8d7862775a41,TimeStamp=19-10-2018 10:
   06:00] [FailureCategory=Cmdlet-InvalidOperationException] FD2ADDFB,Microsoft.Exchange.Management.SystemConfigurati
  onTasks.EnableExchangeCertificate
    + PSComputerName        : sr-XXXXX.domain.lan

As soon as I ran this command mail flow started again.