使用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)
关键知识点
- Graph API资源定位:获取单个应用资源需使用
/applications/{id}路径,全量路径/applications会返回所有应用,不能用于单个应用的数据提取 - 循环数据复用:外层循环已获取应用的核心数据,内层无需重复请求全量接口,减少冗余请求并避免数据错误
- 空值处理:使用
Where-Object { $_ }过滤空的到期日期,避免返回无效的$null值
内容的提问来源于stack exchange,提问作者thekevinkalis
相关产品推荐
相关产品推荐

