IntuneのBitLocker回復キー有無リストを取得する方法

ドハマりかと思った。。
いくつか英語サイト探して情報組み合わせて修正してようやく動作。

１．まず[Azure Portal](https://portal.azure.com/#home)でアプリを登録
![bitappreg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24018/360a896a-ccb5-d985-1aca-7773630581bc.png)
![bitappreg2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24018/89318d72-0f38-5b7e-8364-dbf527abbcc4.png)
２．アクセス権を設定
![bitappperm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24018/db9c8fa9-6698-a6c5-0e4c-f7ef2243e497.png)
![bitappperm2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24018/a2f8d453-f680-e6a1-7cac-515ffbea2e7d.png)
３．管理者の承認
![bitapppermAdmin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24018/775a0808-7590-9197-004f-ab3c70190a26.png)
４．シークレットを作成
![bitappsecret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24018/3863f2ad-0b5c-16a9-6e45-b1906a2bcb8a.png)
５．おソース

```posh:GetBitLockerRecoverKeys.ps1
$AccountName = "username@onmicrosoft.com"
$AccountPassword = "XXXXXXXXXXXXX"
$ClientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
$ClientSecret = "XXXXXXXXXXXXXXXXXXXXXX"
$TenantID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
$GraphUri = "https://graph.microsoft.com"
$GraphVersion = "beta"

Add-Type -AssemblyName System.Web
$ClientSecret = [System.Web.HttpUtility]::UrlEncode($ClientSecret)

# Authentication url
$AzureResourceURI = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token"

# Construct the Body for the POST
$Body = "grant_type=password"`
 + "&username=" + $Accountname `
 + "&client_id=" + $ClientId `
 + "&client_secret=" + $ClientSecret`
 + "&password=" + $AccountPassword `
 + "&scope=https://graph.microsoft.com/.default"

# The result should contain a token for use with Graph
$Response = Invoke-WebRequest -Uri $AzureResourceURI -Method POST -Body $Body -UseBasicParsing
$ResponseJSON = $Response | ConvertFrom-Json

# Add the token to headers for the Graph request
$Headers = @{
Authorization = "Bearer " + $ResponseJSON.access_token
}

#Run API call
$Deviceuri = "$GraphUri/$GraphVersion/devices"
$AllDevices = Invoke-RestMethod -Uri $Deviceuri -Headers $Headers -Method Get

$Body = @{
   grant_type    = "password"
   scope         = "https://graph.microsoft.com/.default"
   client_id     = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
   client_secret = "XXXXXXXXXXXXXXXXXXXXXX"
   username      = "username@onmicrosoft.com"
   password      = "XXXXXXXXXXXXX"
}

$ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantID
/oauth2/v2.0/token" -Method POST -Body $Body

$token = $ConnectGraph.access_token

$headr = @{
Authorization = "Bearer $($token)"
'ocp-client-name' = "My Friendly Client"
'ocp-client-version' = "1.2"
}

$GrapGroupUrl = 'https://graph.microsoft.com/beta/bitlocker/recoveryKeys'

$bitlockerkeys = @()
$bitlockerkeysuri = Invoke-RestMethod -Headers $headr -Uri $GrapGroupUrl -Method Get
$bitlockerkeys += $bitlockerkeysuri.value
while ($bitlockerkeysuri.'@odata.nextLink') {
	$NextBatchRequest = $bitlockerkeysuri.'@odata.nextLink'
	$bitlockerkeysuri = Invoke-RestMethod -Uri $NextBatchRequest -Headers $headr -Method Get
	$bitlockerkeys += $bitlockerkeysuri.value
}

# Get all AAD devices and filter out Windows managed by Intune
$AllDevicesArr = @()
$Deviceuri = "$GraphUri/$GraphVersion/devices?`$filter=operatingSystem eq 'Windows' AND isManaged eq true AND accountEnabled eq true"
$Devices = Invoke-RestMethod -Uri $Deviceuri -Headers $Headers -Method Get
$AllDevicesArr += $Devices.value
while ($Devices.'@odata.nextLink') {
	$NextBatchRequest = $Devices.'@odata.nextLink'
	$Devices = Invoke-RestMethod -Uri $NextBatchRequest -Headers $Headers -Method Get
	$AllDevicesArr += $Devices.value
}
$Devices2 = $AllDevicesArr | Where-Object {$PSItem.managementType -eq 'MDM'}

# For every managed device check if there is a recovery key in AAD
$Results = @()
try {
	foreach ($device in $Devices2) {
		if (($bitlockerkeys | Where-Object { $PSItem.deviceId -eq $device.deviceId } | Measure-Object).Count -gt 0) {

				$Results += [PSCustomObject]@{
					DeviceName       = $device.displayName
					DeviceId         = $device.deviceId
					RecoveryKeyInAAD = $true
					AdditionalInfo   = "$(($bitlockerkeys | Where-Object { $PSItem.deviceId -eq $device.deviceId } | Measure-Object).Count) keys found"
				}
				
		} else {

				$Results += [PSCustomObject]@{
					DeviceName       = $device.displayName
					DeviceId         = $device.deviceId
					RecoveryKeyInAAD = $false
					AdditionalInfo   = ''
				}

		}
	}
} catch {
	Write-Error $device
	Write-Error $_
	break
}

$filename = Get-Date -Format "yyyy-MMdd-HHmmss"
[string]$csvFile = "BitLockerRecoverKeysExists_" + $filename + ".csv"
[string]$csvPath = Join-Path "C:\Temp" $csvFile
$Results | select DeviceName,DeviceId,RecoveryKeyInAAD,AdditionalInfo | Export-Csv -Path $csvPath -Encoding UTF8 -NoTypeInformation
invoke-item $csvPath
```

■ネタ元
Verify Azure AD Bitlocker Keys with Microsoft Graph - Maciej Horbacz
https://universecitiz3n.tech/powershell/Graph-Bitlocker/

azure active directory - "Failed to authorize caller, the caller wasn't owner of the device or one of the admin roles." microsoft-graph - Stack Overflow
https://stackoverflow.com/questions/64905676/failed-to-authorize-caller-the-caller-wasnt-owner-of-the-device-or-one-of-the

Intune – Query Azure AD Bitlocker Keys using Graph API – Azure Cloud & AI Domain Blog
https://azurecloudai.blog/2020/11/24/intune-query-azure-ad-bitlocker-keys-using-graph-api/