[玩转系统] 使用 Microsoft Graph 获取 Office 365 用户的 MFA 状态
作者:精品下载站 日期:2024-12-14 03:43:18 浏览:16 分类:玩电脑
使用 Microsoft Graph 获取 Office 365 用户的 MFA 状态
跟踪用户的 MFA 状态对于保护租户非常重要。目前,我们仍然可以在 PowerShell 中使用 Msol 模块来实现此目的,但 Microsoft 计划停用该模块。因此,我使用 Microsoft Graph 模块重新创建了成功的 MFA 状态脚本。
因此,这个新的 MFA Status 脚本可以执行与旧脚本几乎相同的操作:
- 列出所有用户配置的MFA类型
- 获取所有未启用 MFA 的用户
- 检查单用户的MFA配置
- 检查用户是否是管理员
- 仅获取许可和启用的用户
但使用 Graph,我们还能够检索比旧模块更多的信息。因此现在还检索到以下信息:
- 验证器设备名称
- 获取用户首选的MFA方法
- 检查 Hello for Business 是否已注册
- 自助服务密码重置 (SSPR) 的注册电子邮件地址
目前我们无法检查的是 MFA 是否确实为用户启用或禁用,或者是否强制执行了 MFA(例如用户下次登录后需要配置 MFA)。
与往常一样,您将在文章末尾找到完整的脚本。
使用 Microsoft Graph 和 PowerShell 获取 MFA 状态
Microsoft Graph 不断更新,使用最新版本,我们不必再使用 beta 端点。这意味着我们可以以正常方式连接到 Graph,并使用 Get-MgUser cmdlet 检索所有数据所需的范围。
收集所有用户后,我们可以使用 Get-MgUserAuthenticationMethod
cmdlet 获取所有 MFA 详细信息。
笔记
使用 Graph,我们实际上无法检查用户是否启用或禁用了 MFA。我们只能检查配置了哪些身份验证方法。Microsoft 正在放弃每用户 MFA 配置,我们需要转向 MFA 的条件访问策略。因此,目前,可以在管理中心为特定用户禁用 MFA,我们无法使用 Graph 检测到这一点。
但是,如果您有 Azure P1 或 P2,请查看此脚本。或者,您仍然可以使用旧的 MSOL 模块来执行此操作,因此,如果您仍在使用每用户 MFA,请务必检查此脚本。
要求
您需要安装 Microsoft Graph 模块。该脚本将检查该模块是否已安装,如果没有,您将获得安装它的选项。
获取所有用户及其 MFA 状态
该脚本附带了几个参数,我们可以使用它们来微调导出结果。但默认情况下,它将获取所有许可用户、列出管理员并将 CSV 导出保存在与脚本相同的位置。完成后,脚本将打开 CSV 文件。
因此,要获取所有用户,我们只需运行脚本即可:
# Get all licensed users:
Get-MgMFAStatus.ps1
仅获取没有 MFA 的用户
当您拥有大型租户时,您可能只想查看未启用 MFA 的用户。为此,您可以添加使用开关 -withoutMFAOnly
:
Get-MgMFAStatus.ps1 -withOutMFAOnly
仅检查管理员的 MFA 状态
默认情况下,该脚本将列出所有管理员,但您也可以仅使用 -adminsOnly
开关检查管理员的 MFA 状态:
Get-MgMFAStatus.ps1 -adminsOnly
检查特定用户或选择的用户的状态
还可以检查特定用户的 MFA 状态。我们可以使用 -UserPrincipalName 参数指定用户的 UserPrincipal 名称:
Get-MgMFAStatus -UserPrincipalName '[email protected]'
该参数接受字符串数组,因此您可以用逗号分隔要检索的用户:
Get-MgMFAStatus -UserPrincipalName '[email protected]','[email protected]'
另一种选择是使用 Get-MgUser cmdlet 的过滤器,然后通过管道传输 Get-MgMFAStatus 脚本:
Get-MgUser -Filter "country eq 'Netherlands'" | ForEach-Object { Get-MgMFAStatus -UserPrincipalName $_.UserPrincipalName }
完整的脚本
完整的脚本可以从我的 Github 存储库下载,我建议使用它,以便您始终拥有最新版本。
建议
通过在 PowerShell 配置文件中添加对脚本的引用,快速获取用户的 MFA 状态。请阅读本文中的所有内容。<#
.Synopsis
Get the MFA status for all users or a single user with Microsoft Graph
.DESCRIPTION
This script will get the Azure MFA Status for your users. You can query all the users, admins only or a single user.
It will return the MFA Status, MFA type and registered devices.
Note: Default MFA device is currently not supported https://docs.microsoft.com/en-us/graph/api/resources/authenticationmethods-overview?view=graph-rest-beta
Hardwaretoken is not yet supported
.NOTES
Name: Get-MgMFAStatus
Author: R. Mens - LazyAdmin.nl
Version: 1.2
DateCreated: Jun 2022
Purpose/Change: Added MFA preferred method
.LINK
https://a-d.site
.EXAMPLE
Get-MgMFAStatus
Get the MFA Status of all enabled and licensed users and check if there are an admin or not
.EXAMPLE
Get-MgMFAStatus -UserPrincipalName '[email protected]','[email protected]'
Get the MFA Status for the users John Doe and Jane Doe
.EXAMPLE
Get-MgMFAStatus -withOutMFAOnly
Get only the licensed and enabled users that don't have MFA enabled
.EXAMPLE
Get-MgMFAStatus -adminsOnly
Get the MFA Status of the admins only
.EXAMPLE
Get-MgUser -Filter "country eq 'Netherlands'" | ForEach-Object { Get-MgMFAStatus -UserPrincipalName $_.UserPrincipalName }
Get the MFA status for all users in the Country The Netherlands. You can use a similar approach to run this
for a department only.
.EXAMPLE
Get-MgMFAStatus -withOutMFAOnly| Export-CSV c:\temp\userwithoutmfa.csv -noTypeInformation
Get all users without MFA and export them to a CSV file
#>
[CmdletBinding(DefaultParameterSetName="Default")]
param(
[Parameter(
Mandatory = $false,
ParameterSetName = "UserPrincipalName",
HelpMessage = "Enter a single UserPrincipalName or a comma separted list of UserPrincipalNames",
Position = 0
)]
[string[]]$UserPrincipalName,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $false,
ParameterSetName = "AdminsOnly"
)]
# Get only the users that are an admin
[switch]$adminsOnly = $false,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $false,
ParameterSetName = "Licensed"
)]
# Check only the MFA status of users that have license
[switch]$IsLicensed = $true,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
ParameterSetName = "withOutMFAOnly"
)]
# Get only the users that don't have MFA enabled
[switch]$withOutMFAOnly = $false,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $false
)]
# Check if a user is an admin. Set to $false to skip the check
[switch]$listAdmins = $true,
[Parameter(
Mandatory = $false,
HelpMessage = "Enter path to save the CSV file"
)]
[string]$path = ".\MFAStatus-$((Get-Date -format "MMM-dd-yyyy").ToString()).csv"
)
Function ConnectTo-MgGraph {
# Check if MS Graph module is installed
if (-not(Get-InstalledModule Microsoft.Graph)) {
Write-Host "Microsoft Graph module not found" -ForegroundColor Black -BackgroundColor Yellow
$install = Read-Host "Do you want to install the Microsoft Graph Module?"
if ($install -match "[yY]") {
Install-Module Microsoft.Graph -Repository PSGallery -Scope CurrentUser -AllowClobber -Force
}else{
Write-Host "Microsoft Graph module is required." -ForegroundColor Black -BackgroundColor Yellow
exit
}
}
# Connect to Graph
Write-Host "Connecting to Microsoft Graph" -ForegroundColor Cyan
Connect-MgGraph -Scopes "User.Read.All, UserAuthenticationMethod.Read.All, Directory.Read.All" -NoWelcome
}
Function Get-Admins{
<#
.SYNOPSIS
Get all user with an Admin role
#>
process{
$admins = Get-MgDirectoryRole | Select-Object DisplayName, Id |
%{$role = $_.DisplayName; Get-MgDirectoryRoleMember -DirectoryRoleId $_.id |
where {$_.AdditionalProperties."@odata.type" -eq "#microsoft.graph.user"} |
% {Get-MgUser -userid $_.id }
} |
Select @{Name="Role"; Expression = {$role}}, DisplayName, UserPrincipalName, Mail, Id | Sort-Object -Property Mail -Unique
return $admins
}
}
Function Get-Users {
<#
.SYNOPSIS
Get users from the requested DN
#>
process{
# Set the properties to retrieve
$select = @(
'id',
'DisplayName',
'userprincipalname',
'mail'
)
$properties = $select + "AssignedLicenses"
# Get enabled, disabled or both users
switch ($enabled)
{
"true" {$filter = "AccountEnabled eq true and UserType eq 'member'"}
"false" {$filter = "AccountEnabled eq false and UserType eq 'member'"}
"both" {$filter = "UserType eq 'member'"}
}
# Check if UserPrincipalName(s) are given
if ($UserPrincipalName) {
Write-host "Get users by name" -ForegroundColor Cyan
$users = @()
foreach ($user in $UserPrincipalName)
{
try {
$users += Get-MgUser -UserId $user -Property $properties | select $select -ErrorAction Stop
}
catch {
[PSCustomObject]@{
DisplayName = " - Not found"
UserPrincipalName = $User
isAdmin = $null
MFAEnabled = $null
}
}
}
}elseif($adminsOnly)
{
Write-host "Get admins only" -ForegroundColor Cyan
$users = @()
foreach ($admin in $admins) {
$users += Get-MgUser -UserId $admin.UserPrincipalName -Property $properties | select $select
}
}else
{
if ($IsLicensed) {
# Get only licensed users
$users = Get-MgUser -Filter $filter -Property $properties -all | Where-Object {($_.AssignedLicenses).count -gt 0} | select $select
}else{
$users = Get-MgUser -Filter $filter -Property $properties -all | select $select
}
}
return $users
}
}
Function Get-MFAMethods {
<#
.SYNOPSIS
Get the MFA status of the user
#>
param(
[Parameter(Mandatory = $true)] $userId
)
process{
# Get MFA details for each user
[array]$mfaData = Get-MgUserAuthenticationMethod -UserId $userId
# Create MFA details object
$mfaMethods = [PSCustomObject][Ordered]@{
status = "-"
authApp = "-"
phoneAuth = "-"
fido = "-"
helloForBusiness = "-"
helloForBusinessCount = 0
emailAuth = "-"
tempPass = "-"
passwordLess = "-"
softwareAuth = "-"
authDevice = ""
authPhoneNr = "-"
SSPREmail = "-"
}
ForEach ($method in $mfaData) {
Switch ($method.AdditionalProperties["@odata.type"]) {
"#microsoft.graph.microsoftAuthenticatorAuthenticationMethod" {
# Microsoft Authenticator App
$mfaMethods.authApp = $true
$mfaMethods.authDevice += $method.AdditionalProperties["displayName"]
$mfaMethods.status = "enabled"
}
"#microsoft.graph.phoneAuthenticationMethod" {
# Phone authentication
$mfaMethods.phoneAuth = $true
$mfaMethods.authPhoneNr = $method.AdditionalProperties["phoneType", "phoneNumber"] -join ' '
$mfaMethods.status = "enabled"
}
"#microsoft.graph.fido2AuthenticationMethod" {
# FIDO2 key
$mfaMethods.fido = $true
$fifoDetails = $method.AdditionalProperties["model"]
$mfaMethods.status = "enabled"
}
"#microsoft.graph.passwordAuthenticationMethod" {
# Password
# When only the password is set, then MFA is disabled.
if ($mfaMethods.status -ne "enabled") {$mfaMethods.status = "disabled"}
}
"#microsoft.graph.windowsHelloForBusinessAuthenticationMethod" {
# Windows Hello
$mfaMethods.helloForBusiness = $true
$helloForBusinessDetails = $method.AdditionalProperties["displayName"]
$mfaMethods.status = "enabled"
$mfaMethods.helloForBusinessCount++
}
"#microsoft.graph.emailAuthenticationMethod" {
# Email Authentication
$mfaMethods.emailAuth = $true
$mfaMethods.SSPREmail = $method.AdditionalProperties["emailAddress"]
$mfaMethods.status = "enabled"
}
"microsoft.graph.temporaryAccessPassAuthenticationMethod" {
# Temporary Access pass
$mfaMethods.tempPass = $true
$tempPassDetails = $method.AdditionalProperties["lifetimeInMinutes"]
$mfaMethods.status = "enabled"
}
"#microsoft.graph.passwordlessMicrosoftAuthenticatorAuthenticationMethod" {
# Passwordless
$mfaMethods.passwordLess = $true
$passwordLessDetails = $method.AdditionalProperties["displayName"]
$mfaMethods.status = "enabled"
}
"#microsoft.graph.softwareOathAuthenticationMethod" {
# ThirdPartyAuthenticator
$mfaMethods.softwareAuth = $true
$mfaMethods.status = "enabled"
}
}
}
Return $mfaMethods
}
}
Function Get-Manager {
<#
.SYNOPSIS
Get the manager users
#>
param(
[Parameter(Mandatory = $true)] $userId
)
process {
$manager = Get-MgUser -UserId $userId -ExpandProperty manager | Select @{Name = 'name'; Expression = {$_.Manager.AdditionalProperties.displayName}}
return $manager.name
}
}
Function Get-MFAStatusUsers {
<#
.SYNOPSIS
Get all AD users
#>
process {
Write-Host "Collecting users" -ForegroundColor Cyan
# Collect users
$users = Get-Users
Write-Host "Processing" $users.count "users" -ForegroundColor Cyan
# Collect and loop through all users
$users | ForEach {
$mfaMethods = Get-MFAMethods -userId $_.id
$manager = Get-Manager -userId $_.id
$uri = "https://graph.microsoft.com/beta/users/$($_.id)/authentication/signInPreferences"
$mfaPreferredMethod = Invoke-MgGraphRequest -uri $uri -Method GET
if ($null -eq ($mfaPreferredMethod.userPreferredMethodForSecondaryAuthentication)) {
# When an MFA is configured by the user, then there is alway a preferred method
# So if the preferred method is empty, then we can assume that MFA isn't configured
# by the user
$mfaMethods.status = "disabled"
}
if ($withOutMFAOnly) {
if ($mfaMethods.status -eq "disabled") {
[PSCustomObject]@{
"Name" = $_.DisplayName
Emailaddress = $_.mail
UserPrincipalName = $_.UserPrincipalName
isAdmin = if ($listAdmins -and ($admins.UserPrincipalName -match $_.UserPrincipalName)) {$true} else {"-"}
MFAEnabled = $false
"Phone number" = $mfaMethods.authPhoneNr
"Email for SSPR" = $mfaMethods.SSPREmail
}
}
}else{
[pscustomobject]@{
"Name" = $_.DisplayName
Emailaddress = $_.mail
UserPrincipalName = $_.UserPrincipalName
isAdmin = if ($listAdmins -and ($admins.UserPrincipalName -match $_.UserPrincipalName)) {$true} else {"-"}
"MFA Status" = $mfaMethods.status
"MFA Preferred method" = $mfaPreferredMethod.userPreferredMethodForSecondaryAuthentication
"Phone Authentication" = $mfaMethods.phoneAuth
"Authenticator App" = $mfaMethods.authApp
"Passwordless" = $mfaMethods.passwordLess
"Hello for Business" = $mfaMethods.helloForBusiness
"FIDO2 Security Key" = $mfaMethods.fido
"Temporary Access Pass" = $mfaMethods.tempPass
"Authenticator device" = $mfaMethods.authDevice
"Phone number" = $mfaMethods.authPhoneNr
"Email for SSPR" = $mfaMethods.SSPREmail
"Manager" = $manager
}
}
}
}
}
# Connect to Graph
ConnectTo-MgGraph
# Get Admins
# Get all users with admin role
$admins = $null
if (($listAdmins) -or ($adminsOnly)) {
$admins = Get-Admins
}
# Get MFA Status
Get-MFAStatusUsers | Sort-Object Name | Export-CSV -Path $path -NoTypeInformation
if ((Get-Item $path).Length -gt 0) {
Write-Host "Report finished and saved in $path" -ForegroundColor Green
# Open the CSV file
Invoke-Item $path
}else{
Write-Host "Failed to create report" -ForegroundColor Red
}
总结
启用 MFA 确实有助于保护您的租户。此 PowerShell 脚本允许您轻松检查用户的 MFA 状态。
请务必查看本文以及 Office 365 的其他 20 个安全提示。您可以在此处找到此脚本的 Msol 版本,以及在此处找到基于 Microsoft Entra 的新版本。
如果您发现此脚本有用,请分享。如果您有任何疑问,请在下面发表评论。
您可能还喜欢以下 PowerShell 报告脚本之一:
- 邮箱权限报告
- 邮箱大小报告
- OneDrive 大小报告
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag