我一直在关注几个解决方案来使用 MS Graph API 检索 Azure AD 注册的 BitLocker 密钥列表。我正在使用的代码是:
$AzureTokenURI = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token"
$BitlockerURI = "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys"
$TokenRequestBody = "grant_type=password&username=$($SACred.UserName)&client_id=$ClientId&client_secret=$ClientSecret&password=$($SACred.GetNetworkCredential().Password)&scope=https://graph.microsoft.com/.default"
$TSStart = [datetime]::Now
$BitlockerKeys = @()
while ($BitlockerURI) {
If (!$ResponseJSON -or ([datetime]::Now - $TSStart).TotalSeconds -gt ($ResponseJSON.expires_in - 300)) {
$TSStart = [datetime]::Now
$ResponseJSON = Invoke-WebRequest -Uri $AzureTokenURI -Method POST -Body $TokenRequestBody -UseBasicParsing |ConvertFrom-Json
$BitlockerHeader = @{Authorization = "$($ResponseJSON.token_type) $($ResponseJSON.access_token)"; 'ocp-client-name' = 'BL_List_Keys_IDs'; 'ocp-client-version' = '1.0'}
Write-Host "Token Renewed"
}
$BitlockerKeysResponse = Invoke-RestMethod -Uri $BitlockerURI -Headers $BitlockerHeader -Method Get
$BitlockerKeys += $BitlockerKeysResponse.Value
Write-Host $BitlockerKeys.Count.ToString().PadRight(6), (New-TimeSpan $TSStart ([datetime]::Now)).ToString('hh\:mm\:ss\.fff')
$BitlockerURI = $BitlockerKeysResponse.'@odata.nextLink'
}
现在一切正常,但是当密钥到来时(总共不到 5,000 个)我意识到每次调用只带回几个密钥,我似乎无法找到一种方法来强制服务器端分页到一个合理的值(比如每次通话几千个键)。有关前 30 个键,请参见下面的输出:
钥匙 | 时间流逝 |
---|---|
1 | 00:00:13.343 |
5 | 00:00:24.452 |
6 | 00:00:31.984 |
10 | 00:00:40.765 |
14 | 00:00:49.171 |
18 | 00:00:56.577 |
22 | 00:01:03.937 |
27 | 00:01:12.468 |
30 | 00:01:20.218 |
这意味着下载 5k 个密钥大约需要 2 个小时,这几乎与逐个查询每个设备一样糟糕,这违背了在第一个实例中使用“/informationProtection/bitlocker/recoveryKeys”方法的目的。列表中只有一个调用返回了 200 个键,耗时 8 秒,这告诉我经过的时间不取决于返回的键数。因此,使此方法有效的唯一方法是强制同时返回数百个键。如何强制 API 每次调用返回数百或数千个密钥?