在 Azure AD 组中搜索多个字符串

DDE*_*DEX 3 powershell azure-active-directory

我们有具有以下命名约定的 Azure AD 组:Department_GroupName_Membership 类型(具有三个选项:访问者/成员/所有者)。我需要能够将用户添加到 Department_XY 的所有组,成员类型为“Member”。即类似的东西Department_XY_{GroupName}_Member。我无法弄清楚如何检索此类组的列表。应由Cmdlet的-Filter参数采用的ODATA 过滤器子句Get_AzureAdGroup工作异常。例如,Get-AzureADGroup -Filter "startswith(DisplayName, 'Department_XY')"工作正常,但是Get-AzureADGroup -Filter "endswith(DisplayName, 'Member')会引发错误。所以我认为有更好的方法来做到这一点?我安装了 AzureAD 模块。

HAL*_*256 7

要扩展@AdminOfThings 答案以及其他有关-Fliter参数的内容,让我们调查一下发生了什么......

使用:AzureAD 版本 2.0.2.76

docs Get-AzureADGroup -Filter参数使用“ OData v3.0 协议”(我在这里故意使用大引号)。但是当您实际尝试使用更高级的过滤器参数时substringof()endswith()我们会收到错误消息:

Get-AzureADGroup : Error occurred while executing GetGroups
Code: Request_UnsupportedQuery
Message: Unsupported Query.
Run Code Online (Sandbox Code Playgroud)

所以,那没有用。好的,让我们切换到使用-SearchString参数,它“应该”(大引号)执行GetVague操作又名 OData$search操作(在这种情况下,我们尝试将其误用为$substring()操作)。所以让我们试试:

Get-AzureADGroup -SearchString "Department_XY"
Run Code Online (Sandbox Code Playgroud)

按预期返回结果。现在让我们尝试在DisplayName, "Member"末尾搜索一些内容:

Get-AzureADGroup -SearchString "Member"
Run Code Online (Sandbox Code Playgroud)
No Results.
Run Code Online (Sandbox Code Playgroud)

这意味着实际发生的是它正在执行$filter=startswith()查询,而不是$search预期的查询。

文档也说,-SearchString不接受通配符,也没有-Filter参数,和的OData协议来过滤不使用通配符。它只进行直接字符匹配。所以这就是为什么要尝试:

Get-AzureADGroup -SearchString "Department_XY*"
Run Code Online (Sandbox Code Playgroud)

不返回任何结果。这是因为我们不是在搜索以“ Department_XY”开头的任何内容,我们实际上是在明确搜索以“ Department_XY*”开头的任何内容,它将末尾的星号视为名称的一部分。

那么问题来了,为什么这不能按预期工作?我们习惯于使用带有通配符、正则表达式和疯狂过滤选项的 PowerShell cmdlet。我们基本上已经被 Active Directory PowerShell 模块和我们可以对其执行的操作宠坏了。为了充分了解为什么,我们要了解什么是怎么回事,当我们运行Get-AzureADGroup

本质上,AzureAD 模块是一个巨大的 PowerShell 包装器,它可以调用Microsoft Graph API并将获取/设置/安全/令牌复杂性从我们身边抽象出来。这就是为什么-Filter使用OData v3.0 协议语法而不是像通配符/正则表达式这样更“PowerShell-y”的东西。这就是为什么完整的错误消息中有一个HttpStatusCode: BadRequest

Get-AzureADGroup : Error occurred while executing GetGroups
Code: Request_UnsupportedQuery
Message: Unsupported Query.
RequestId: 3455cecd3-bcbc-4257-9be6-69e05a123e26
DateTimeStamp: Wed, 01 Jan 2020 01:01:01 GMT
HttpStatusCode: BadRequest
HttpStatusDescription: Bad Request
HttpResponseStatus: Completed
Run Code Online (Sandbox Code Playgroud)

微软图形 API

让我们探索Microsoft Graph API并弄清楚发生了什么。为此,让我们使用Microsoft Graph Explorer。登录,授予所需的权限,包括Group.Read.All执行查询所需的权限。

当我们执行-Filter查询时,我们正在执行的是:

电源外壳:

Get-AzureADGroup -Filter "startswith(DisplayName, 'Department_XY')"
Run Code Online (Sandbox Code Playgroud)

Microsoft Graph API 调用:

https://graph.microsoft.com/v1.0/groups?$filter=startswith(displayName,'Department_XY')
Run Code Online (Sandbox Code Playgroud)

这两个操作都返回我们预期的数据行。

因此,让我们尝试使用以下命令进行 OData 过滤器查询endswith()

电源外壳:

Get-AzureADGroup -Filter "endswith(DisplayName, 'Member')"
Run Code Online (Sandbox Code Playgroud)
Get-AzureADGroup : Error occurred while executing GetGroups
Code: Request_UnsupportedQuery
Message: Unsupported Query.
RequestId: 3455cecd3-bcbc-4257-9be6-69e05a123e26
DateTimeStamp: Wed, 01 Jan 2020 01:01:01 GMT
HttpStatusCode: BadRequest
HttpStatusDescription: Bad Request
HttpResponseStatus: Completed
Run Code Online (Sandbox Code Playgroud)

Microsoft Graph API 调用:

https://graph.microsoft.com/v1.0/groups?$filter=endswith(DisplayName, 'Member')
Run Code Online (Sandbox Code Playgroud)
{
    "error": {
        "code": "Request_UnsupportedQuery",
        "message": "Unsupported Query.",
        "innerError": {
            "request-id": "19ab3d69-77f7-45ea-b871-4dd518509193",
            "date": "2020-01-08T17:53:07"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这两种方法都为我们提供了相同的“不支持的查询”。错误。

当我们查看有关过滤器查询参数的 API 文档时,我们看到仅支持 OData 查询过滤器的一个子集,最重要的是,过滤器部分末尾的注释说:

注意:以下$filter运营商不支持Azure的AD资源:negtgeltle,和not。该contains字符串操作目前不支持在任何Microsoft图形资源。

这意味着我们剩下三种可能的filter操作:

  • 等于 ( eq)
  • startswith
  • any

这意味着,目前还没有一种过滤组名其他任何方式除了精确匹配,或方式startswith在微软图表源

好坚持!怎么样-SearchString?这相当于$searchOData 查询参数。它可以在 PowerShell 中运行,为什么不能在 Graph API 中运行?

电源外壳:

Get-AzureADGroup -SearchString "Department_XY"
Run Code Online (Sandbox Code Playgroud)
...Returns Group Results...
Run Code Online (Sandbox Code Playgroud)

Microsoft Graph API 调用:

https://graph.microsoft.com/v1.0/groups?$search="Department_XY"
Run Code Online (Sandbox Code Playgroud)
{
    "error": {
        "code": "Request_UnsupportedQuery",
        "message": "This query is not supported.",
        "innerError": {
            "request-id": "67fe0362-d78d-4de3-b52a-c8bfce109f98",
            "date": "2020-01-08T18:23:10"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?查看搜索查询参数的文档,在顶部,有注释:

注意:您目前只能搜索消息和人员集合。一个 $search请求最多返回 250 个结果。您不能在搜索请求中使用$filter$orderby

这意味着没有实现按组搜索。PowerShell cmdlet 所做的是提供一个-SearchString参数,目的是search将来可以将其连接到适当的查询参数,但就目前而言,它通过$filter=startswith()查询“伪造”了它。一旦 Microsoft Graph API 支持更多查询参数和更多更新,这种“伪造”可能会发生变化。


因此,我们已经彻底穷尽了所有在源头进行过滤的选项。我们必须在我们的 PowerShell 客户端上进行所有过滤。我们可以:

  • 聪明一点,至少使用@AdminOfThings 答案根据起始字符串预过滤组。
  • 使用-SearchString因为这样我们就没有明确地摆弄过滤器查询格式。
  • 正如@MerillFernando提到的,我们必须指定-All $true参数,因为正如我们所知,它正在向 Microsoft Graph API 发出请求,并且默认情况下它只返回前 100 个条目。
    • 为了扩展@AllenWu 答案不起作用的原因,当您在Get-AzureADGroup没有-All $true开关的情况下运行 a 时,它只会返回 100 个组。这 100 个组是“随机”选择的。如果您有 1000 个组,则您尝试选择的组很可能不在您获得的第一批 100 个组中。
  • 我个人喜欢将条目保存到一个变量中,这样我就可以运行多个不同的查询/过滤器,直到得到我想要的结果,而无需发出多个 API 请求。
  • 一旦它位于 PowerShell 中的变量中,我们就可以使用我们最喜欢的过滤/正则表达式方法来匹配我们想要的。
  • 在此用例中,EndsWith()用于在其他过滤方法(如-like或 regex)之上进行过滤。我认为@AdminOfThings有正确的想法以这种方式过滤,因为该函数将向后解析字符串,这比-like过滤器必须在每次评估时处理整个字符串的速度和效率高一个数量级。

所以,TLDR。你最终得到的代码是:

$groups = Get-AzureADGroup -SearchString 'Department_XY' -All $true
$groups | Where-Object { $_.DisplayName.EndsWith('Member') }
Run Code Online (Sandbox Code Playgroud)