在Azure功能应用程序中使用PowerShell连接到不同的Azure AD租户

在Azure功能应用程序中使用PowerShell连接到不同的Azure AD租户,azure,powershell,azure-active-directory,azure-functions,Azure,Powershell,Azure Active Directory,Azure Functions,我正在尝试创建一个系统,在该系统中,PowerShell从多个租户收集数据,并在报告中显示数据。需要检查的数据点之一是管理员是否启用了MFA。为了提取这些数据,我使用以下方法 $credentials = <credentials>; Connect-MSOLService -Credential $credentials; foreach ($role in Get-MsolRole) { foreach ($adminUser in (Get-MsolRoleM

我正在尝试创建一个系统,在该系统中,PowerShell从多个租户收集数据,并在报告中显示数据。需要检查的数据点之一是管理员是否启用了MFA。为了提取这些数据,我使用以下方法

$credentials = <credentials>;    
Connect-MSOLService -Credential $credentials;

foreach ($role in Get-MsolRole) {
    foreach ($adminUser in (Get-MsolRoleMember -All -RoleObjectId $role.ObjectId -MemberObjectTypes @("User"))) {
        $isMFA = ($adminUser.StrongAuthenticationRequirements -match 'Microsoft.Online.Administration.StrongAuthenticationRequirement').Count -gt 0;
        #Do stuff
    }
}
$credentials=;
连接MSOLService-凭证$凭证;
foreach($Get MsolRole中的角色){
foreach($adminUser in(Get-MsolRoleMember-All-RoleObjectId$role.ObjectId-MemberObjectTypes@(“用户”)){
$isMFA=($adminUser.StrongAuthenticationRequirements-匹配'Microsoft.Online.Administration.StrongAuthenticationRequirements')。计数-gt 0;
#做事
}
}
这很有效。问题是,此脚本正在队列触发的azure函数中运行。它由计时器触发,这意味着所有触发器将同时运行。当建立第一个连接时,所有其他数据请求从同一租户提取数据

我有没有办法确保每个请求都有自己的连接,或者限制msol连接的范围


我能想到的唯一解决方案是同步运行脚本,但这会导致非常差的性能。

事实上,当由队列触发时,同一函数的多个运行似乎根本不是孤立的

您可以采取的一种方法是使用
Start job
将应该独立运行的PowerShell代码包装到自己的PowerShell作业中。下面是一个我测试成功的例子

# Receive queue message
$input = Get-Content $queueItem -Raw

# Pass the input queue message as a parameter to a new job.
$job = Start-Job -ArgumentList $input -ScriptBlock {

    param($queueMessage)

    # Load the MSOnline PowerShell module 
    Import-Module $env:CONTOSO_PathToMSOnline

    # Retrieve the credentials from where they're securely stored
    $credentials = ... # e.g. get from Key Vault

    # Connect to Azure AD. This connection is only used by this job.
    Connect-MsolService -Credential $credentials

    # Do something with MSOnline...
}

# Wait for the job to complete, receive results, then clean up.
Receive-Job -Wait -Job $job -AutoRemoveJob
根据我的测试,这应该可以满足你的隔离需求。但是,请记住,您正在为此构建一个全新的PowerShell主机实例,这可能会产生意外后果(例如,内存使用量增加,加载时间延长)

当我在做这件事时,我想建议对您的流程进行调整,以确定启用了每用户MFA的管理员(假设您不想重复计算属于多个角色的管理员):


您如何解释使用条件访问策略为管理员启用MFA的租户?()这是否是功能应用程序中的同一功能,针对不同租户触发?或者是功能应用程序中的不同功能,每个功能为不同的租户触发?功能应用程序中的相同功能,每个功能为不同的租户触发凭据。我有一个可变数量的租户,所以它必须是一个单一的功能。第一个问题呢?您计划如何向通过条件访问启用了MFA(而不是每个用户MFA)的管理员发送地址?1)您提到,运行“队列中的脚本触发了azure函数”,但它是在计时器上触发的。哪个是真正的触发器?2) $credentials是否需要在每次调用函数时都是唯一的?这似乎很有希望。但是,在作业中运行时,该功能无法再检测MSOnline模块。我似乎也无法导入它。您得到的具体错误是什么?您是否从作业内部加载MSOnline模块?我已将该模块放置在模块文件夹中,因此当函数触发时,它应自动包括在内。这以前是有效的,没有任何代码行包括模块。确切的错误消息是:“术语‘Connect MSOLService’未被识别为cmdlet、函数、脚本文件或可操作程序的名称。请检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。”这可能是作业中预加载的模块文件夹不同。尝试以下两件事:导入模块MSOnline(希望它能从任何已经存在的地方获取它)。如果这不起作用,请尝试2)导入模块“C:/path/to/Module/MSOnline.psd1”(明确告诉它模块的位置)。由于某种原因,我无法解释,使用完整路径是有效的,但只有在更新模块之后。自动包含的版本与以前的版本一起工作,因此我对此没有解释。但是,该脚本现在可以按预期工作,并且没有受到明显的性能影响。非常感谢你!!
# Iterate over all admins of all roles, and check if they have per-user MFA enabled.

$admins = @{} # To keep track of which admins we've already seen

foreach ($role in Get-MsolRole) {

    $roleMembers = Get-MsolRoleMember -All -RoleObjectId $role.ObjectId `#`
                                      -MemberObjectTypes @("User")

    foreach ($user in $roleMembers) {

        if ($admins.ContainsKey($user.ObjectId)) {
            # We've already seen this user, skip it.
        } else {
            $admins[$user.ObjectId] = $true # Mark as admin we've seen

            # Determine if per-user MFA is enabled or enforced
            $isMfaEnabledOrEnforced = $user.StrongAuthenticationRequirements.Count -gt 0

            # Do something...    
        }
    }
}