You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Graph PowerShell获取应用注册密钥/证书到期日期问题排查

问题:获取应用注册密钥到期日期时数据重复

问题场景

尝试通过Graph API获取所有应用注册的名称、ID及密钥到期日期,并封装为PSCustomObject,但执行后每个应用的Credentials字段都显示所有应用的到期日期,而非对应应用自身的密钥信息。

原代码如下:

# Loop through all apps and add to PSCustomObject
$uri = 'https://graph.microsoft.com/beta/applications?$select=displayName, passwordCredentials, id'
 
$result = do {
    $Data = Invoke-RestMethod -Method Get -Uri $uri -Headers $Headers
    $uri = $Data.'@odata.nextLink'
 
    foreach ($app in $Data.value) {
 
        $appUri = 'https://graph.microsoft.com/beta/applications?$select=displayName, passwordCredentials, id'
        $allAppSecretsExpiry = do {
            $cred = Invoke-RestMethod -Method Get -Uri $appUri -Headers $Headers
            $appUri = $cred.'@odata.nextLink'
            if ($cred) {
                $cred.value.passwordCredentials.endDateTime
            }
        }
        while ($appUri)
 
        [pscustomobject]@{
            displayName = $app.displayName
            id          = $app.id
            Credentials = $allAppSecretsExpiry
        }
    }
}
while ($uri)

错误原因

核心问题在于foreach循环内部的逻辑错误:

  • 处理单个应用时,重新调用了全量应用列表的Graph接口,而非仅获取当前应用的密钥信息
  • 导致$allAppSecretsExpiry收集的是所有应用的到期日期,最终每个应用对象都复用了这份全量数据

修正方案

方案1:直接使用外层获取的应用数据(高效无冗余)

外层循环已经通过$select获取了每个应用的passwordCredentials,无需重复请求接口,直接提取当前应用的到期日期即可:

$uri = 'https://graph.microsoft.com/beta/applications?$select=displayName, passwordCredentials, id'
 
$result = do {
    $Data = Invoke-RestMethod -Method Get -Uri $uri -Headers $Headers
    $uri = $Data.'@odata.nextLink'
 
    foreach ($app in $Data.value) {
        # 提取当前应用的所有密钥到期日期,空值则返回空数组
        $appSecretsExpiry = $app.passwordCredentials.endDateTime | Where-Object { $_ }
        
        [pscustomobject]@{
            displayName = $app.displayName
            id          = $app.id
            Credentials = $appSecretsExpiry
        }
    }
}
while ($uri)

方案2:调用单个应用接口确保数据最新(适合需要实时数据的场景)

如果需要确保获取的是最新的密钥信息,可以通过应用ID拼接单个应用的接口路径,而非请求全量列表:

$uri = 'https://graph.microsoft.com/beta/applications?$select=displayName, id'
 
$result = do {
    $Data = Invoke-RestMethod -Method Get -Uri $uri -Headers $Headers
    $uri = $Data.'@odata.nextLink'
 
    foreach ($app in $Data.value) {
        # 拼接单个应用的接口路径
        $singleAppUri = "https://graph.microsoft.com/beta/applications/$($app.id)?$select=displayName,passwordCredentials"
        $singleAppData = Invoke-RestMethod -Method Get -Uri $singleAppUri -Headers $Headers
        
        $appSecretsExpiry = $singleAppData.passwordCredentials.endDateTime | Where-Object { $_ }
        
        [pscustomobject]@{
            displayName = $singleAppData.displayName
            id          = $app.id
            Credentials = $appSecretsExpiry
        }
    }
}
while ($uri)

关键知识点

  1. Graph API资源定位:获取单个应用资源需使用/applications/{id}路径,全量路径/applications会返回所有应用,不能用于单个应用的数据提取
  2. 循环数据复用:外层循环已获取应用的核心数据,内层无需重复请求全量接口,减少冗余请求并避免数据错误
  3. 空值处理:使用Where-Object { $_ }过滤空的到期日期,避免返回无效的$null值

内容的提问来源于stack exchange,提问作者thekevinkalis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:16:01