概述
我想要一种查询Azure AD的方法,并返回分配给Azure中不同资源组的Azure AD组的列表。
当前解决方案
当前,我有一个Powershell脚本作为服务原理运行,并通过Azure进行身份验证,然后它将获得当前的订阅。基于此搜索已登录的用户,并返回分配给该用户的所有安全组。然后根据AD组分配给的所有资源组进行检查,这将返回登录用户可以访问的资源组中VM的列表。
这确实有效,但是运行大约需要10分钟。每个订阅我们有100个资源组,而且速度很慢。
我粘贴了以下代码,并删除了所有私人信息。
问题
我正在使用Az Powershell 2.4.0库创建代码。
function userLogin($azureAplicationId, $azureAppPassword)
{
$azureTenantId= ""
$azurePassword = ConvertTo-SecureString $azureAppPassword -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
}
function userRGAccessCheck($RG)
{
$resoruceGroupChoice = Read-Host -Prompt "Enter Resource Group Name "
}
function userRTAccessCheck($RName)
{
$resoruceNameChoice = Read-Host -Prompt "Enter VM Name "
}
$subAccess = Read-Host -Prompt "Enter Subscription, Press (1) OR (2): `n(1) Microsoft Azure Enterprise Non-Production `n(2) Microsoft Azure Enterprise Production`n"
if ($subAccess -eq 1)
{
$azureAplicationId =""
$azureAppPassword = ""
userLogin -azureAplicationId $azureAplicationId -azureAppPassword $azureAppPassword
#userRGAccessCheck -RG $reresoruceGroupChoice
} elseif ($subAccess -eq 2)
{
$azureAplicationId =""
$azureAppPassword = ""
userLogin -azureAplicationId $azureAplicationId -azureAppPassword $azureAppPassword
#userRGAccessCheck -RG $reresoruceGroupChoice
#userRTAccessCheck -RName $resoruceNameChoice
} else
{
Write-Host "Please Enter 1 OR 2"
}
# Arrays for app
$groupArray = @()
$ADAccessGroupArray = @()
$resourceGroupArray = @()
$userObjectID = "USER_OBJECT_ID"
# Get AD User Groups and list of resource groups
$groupArray += (Get-AzADGroup -SearchString 'SS_*' | Select-Object -ExpandProperty Id)
foreach($group in $groupArray)
{
if(Get-AzADGroupMember -GroupObjectId $group | Where-Object {$_.Id -eq $userObjectID})
{
$ADAccessGroupArray += $group
Write-Host "User has access to group: " $group
} else
{
Write-Host "User does not have access to group: " $group
}
}
# Get a list of resource groups
$resourceGroupArray += Get-AzResourceGroup | Select-Object -ExpandProperty ResourceGroupName
# Check if the AD group has been assigned to the resource group
foreach ($resourceGroupName in $resourceGroupArray)
{
foreach ($ADAccessGroup in $ADAccessGroupArray)
{
if(Get-AzRoleAssignment -ResourceGroupName $resourceGroupName | Where-Object {$_.ObjectId -eq $ADAccessGroup})
{
Write-Host "User has access to group: " $resourceGroupName
}
}
}
$groupArray = $null
$ADAccessGroupArray = $null
$resourceGroupArray = $null
预先感谢
答案 0 :(得分:1)
我进行了一些修改,应该会有所帮助。
function userLogin($azureAplicationId, $azureAppPassword)
{
$azureTenantId= ""
$azurePassword = ConvertTo-SecureString $azureAppPassword -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
}
function userRGAccessCheck($RG)
{
$resoruceGroupChoice = Read-Host -Prompt "Enter Resource Group Name "
}
function userRTAccessCheck($RName)
{
$resoruceNameChoice = Read-Host -Prompt "Enter VM Name "
}
$subAccess = Read-Host -Prompt "Enter Subscription, Press (1) OR (2): `n(1) Microsoft Azure Enterprise Non-Production `n(2) Microsoft Azure Enterprise Production`n"
if ($subAccess -eq 1)
{
$azureAplicationId =""
$azureAppPassword = ""
userLogin -azureAplicationId $azureAplicationId -azureAppPassword $azureAppPassword
#userRGAccessCheck -RG $reresoruceGroupChoice
} elseif ($subAccess -eq 2)
{
$azureAplicationId =""
$azureAppPassword = ""
userLogin -azureAplicationId $azureAplicationId -azureAppPassword $azureAppPassword
#userRGAccessCheck -RG $reresoruceGroupChoice
#userRTAccessCheck -RName $resoruceNameChoice
} else
{
Write-Host "Please Enter 1 OR 2"
}
# Arrays for app
$groupArray = @()
$ADAccessGroupArray = @() -as [System.Collections.Arraylist] # Using Arraylist type
$resourceGroupArray = @()
$userObjectID = "USER_OBJECT_ID"
# Get AD User Groups and list of resource groups
$groupArray = (Get-AzADGroup -SearchString 'SS_*' | Select-Object -ExpandProperty Id) # Removed += because it is unnecessary
foreach($group in $groupArray)
{
if((Get-AzADGroupMember -GroupObjectId $group).where({$_.Id -eq $userObjectID},'First')) # Used where method
{
$null = $ADAccessGroupArray.Add($group) # Add group to arraylist and suppress output. Removed += because it is a slow operation here.
Write-Host "User has access to group: " $group
} else
{
Write-Host "User does not have access to group: " $group
}
}
# Get a list of resource groups
$resourceGroupArray = Get-AzResourceGroup | Select-Object -ExpandProperty ResourceGroupName # Removed += because it is unnecessary
# Check if the AD group has been assigned to the resource group
foreach ($resourceGroupName in $resourceGroupArray)
{
if((Get-AzRoleAssignment -ResourceGroupName $resourceGroupName).where({$_.ObjectId -in $ADAccessGroupArray},'First')) # used where method
{
Write-Host "User has access to group: " $resourceGroupName
}
}
$groupArray = $null
$ADAccessGroupArray = $null
$resourceGroupArray = $null
我在更改的行中添加了注释。以下是更改的摘要:
$ADAccessGroupArray
设置为arraylist类型。这样我们就可以访问固有的Add()
方法来对其进行更新。如果我们使用不可变的数组,则必须创建一个新数组以添加更多条目。更新数组的一种方法是使用+=
,随着数组大小的增加,这是一种非常低效的操作。
+=
并不是最有效的方法。有时这是可以忽略的操作,但是除非您知道它可以忽略,否则我会避免这样做。+=
,因为当您将变量设置为返回数组的命令输出时,它们不是必需的。结果将是不包含+=
的数组。在某些情况下,您的命令返回一个值,然后您的变量可能不会成为数组。可以使用,
一元运算符或提前声明数组来解决此问题。Where-Object
方法代替了where()
。 where-object
(和where()
)不仅在完成任何操作之前都等待LHS操作完成,而且还会在返回结果之前先对所有流水线项目进行枚举。使用where()
方法,我们可以访问模式。在您的两种情况下,我都使用'First'
模式,以便where()
一旦找到第一个条件匹配项就将停止处理。如果您有1000个对象的列表,并且匹配项在该列表的上半部之内,这将非常有用。foreach
$resourceGroupArray
循环内的嵌套foreach
循环。这可以通过更新下一个where()
条件以使用-in
运算符来实现。 -in
使您可以在一个集合中找到一个项目,这就是您为每个组所做的工作。因此,我们将Get-AzRoleAssignment
的呼叫次数从ResourceGroups x Groups
减少到ResourceGroups
。这里应该可以节省大量时间。