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 模块。
要扩展@AdminOfThings 答案以及其他有关-Fliter
参数的内容,让我们调查一下发生了什么......
使用:AzureAD 版本 2.0.2.76
从docs Get-AzureADGroup
-Filter
参数使用“ OData v3.0 协议”(我在这里故意使用大引号)。但是当您实际尝试使用更高级的过滤器参数时substringof()
,endswith()
我们会收到错误消息:
Run Code Online (Sandbox Code Playgroud)Get-AzureADGroup : Error occurred while executing GetGroups Code: Request_UnsupportedQuery Message: Unsupported Query.
所以,那没有用。好的,让我们切换到使用-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)
Run Code Online (Sandbox Code Playgroud)No Results.
这意味着实际发生的是它正在执行$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
:
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
让我们探索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)
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
Microsoft Graph API 调用:
https://graph.microsoft.com/v1.0/groups?$filter=endswith(DisplayName, 'Member')
Run Code Online (Sandbox Code Playgroud)
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" } } }
这两种方法都为我们提供了相同的“不支持的查询”。错误。
当我们查看有关过滤器查询参数的 API 文档时,我们看到仅支持 OData 查询过滤器的一个子集,最重要的是,过滤器部分末尾的注释说:
注意:以下
$filter
运营商不支持Azure的AD资源:ne
,gt
,ge
,lt
,le
,和not
。该contains
字符串操作目前不支持在任何Microsoft图形资源。
这意味着我们剩下三种可能的filter
操作:
eq
)startswith
any
这意味着,目前还没有一种过滤组名其他任何方式除了精确匹配,或方式startswith
,在微软图表源。
好坚持!怎么样-SearchString
?这相当于$search
OData 查询参数。它可以在 PowerShell 中运行,为什么不能在 Graph API 中运行?
电源外壳:
Get-AzureADGroup -SearchString "Department_XY"
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)...Returns Group Results...
Microsoft Graph API 调用:
https://graph.microsoft.com/v1.0/groups?$search="Department_XY"
Run Code Online (Sandbox Code Playgroud)
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" } } }
这是怎么回事?查看搜索查询参数的文档,在顶部,有注释:
注意:您目前只能搜索消息和人员集合。一个
$search
请求最多返回 250 个结果。您不能在搜索请求中使用$filter
或$orderby
。
这意味着没有实现按组搜索。PowerShell cmdlet 所做的是提供一个-SearchString
参数,目的是search
将来可以将其连接到适当的查询参数,但就目前而言,它通过$filter=startswith()
查询“伪造”了它。一旦 Microsoft Graph API 支持更多查询参数和更多更新,这种“伪造”可能会发生变化。
因此,我们已经彻底穷尽了所有在源头进行过滤的选项。我们必须在我们的 PowerShell 客户端上进行所有过滤。我们可以:
-SearchString
因为这样我们就没有明确地摆弄过滤器查询格式。-All $true
参数,因为正如我们所知,它正在向 Microsoft Graph API 发出请求,并且默认情况下它只返回前 100 个条目。
Get-AzureADGroup
没有-All $true
开关的情况下运行 a 时,它只会返回 100 个组。这 100 个组是“随机”选择的。如果您有 1000 个组,则您尝试选择的组很可能不在您获得的第一批 100 个组中。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)