はじめに...
調査した内容を時系列にまとめた資料なので、その点ご了承ください。
- そろそろ新しいMacを手配せねば…
目次
- 実行環境
- 実現したいこと
- 作業の流れ
- 例題
- (i) 要件の定義
- (ii) アクセス許可の確認
- (iii) Azure Active Directoryにてアプリ登録
- (iv) アクセス許可の追加と管理者の同意
- (v) クライアントシークレットを作成
- (vi) Powershellの雛形を更新し、動作を確認する
- アクセス許可でエラーが出た時には...
- まとめ
1. 実行環境
項目 | 情報 |
---|---|
OS | macOS 11.6 |
HW | MacBook Air (11-inch, Mid 2013) |
pwsh | 7.2.0 |
MDM環境 | microsoft intune |
2. 実現したいこと
- Azureのアプリ登録からアクセス権限の設定、テストまで気軽に実施できる手順を準備したい
- ※今回はClientSecretを使って実装する
3. 作業の流れ
以下の流れを元に例題を定めて実践する
i. 今回の要件を定義する
- xxxxxの情報を取得したい、xxxxxxの情報を追加したいなど
ii. Microsoft Graph REST API v1.0 リファレンスからURLと必要なアクセス許可を確認する - https://docs.microsoft.com/ja-jp/graph/api/overview?view=graph-rest-1.0
-
https://docs.microsoft.com/ja-jp/graph/api/overview?view=graph-rest-beta
iii. Azure Active Directoryを使ってアプリの登録をする -
https://portal.azure.com/
iv. アプリにアクセス許可の追加と管理者の同意を与える
v. クライアントシークレットを作成する
vi. Powershellの雛形を更新し、動作を確認する
4. 例題
業務用デバイス(もちろんmac)の登録と確認を行いたい
5. (i) 要件の定義
intuneにて業務用デバイスのSerial登録と登録結果の確認を行う
6. (ii) アクセス許可の確認
Microsoft Graph REST API リファレンスからアクセスするURLと必要なアクセス許可を確認する
- https://docs.microsoft.com/ja-jp/graph/api/overview?view=graph-rest-1.0
- https://docs.microsoft.com/ja-jp/graph/api/overview?view=graph-rest-beta
作業内容 | URL(抜粋) | アクセス権 |
---|---|---|
業務用デバイスの登録 | POST /deviceManagement/importedDeviceIdentities | DeviceManagementServiceConfig.ReadWrite.All |
業務用デバイスの一覧 | GET /deviceManagement/importedDeviceIdentities | DeviceManagementServiceConfig.Read.All, DeviceManagementServiceConfig.ReadWrite.All |
7. (iii) Azure Active Directoryにてアプリ登録
- Azure Active Directory > アプリの登録を開き、「新規登録」ボタンを押下する
- 名前は任意の名前を指定(ここでは、intune-device-get)
- オプションは、テストのため、「この組織ディレクトリのみに含まれるアカウント (none のみ - シングル テナント)」を指定
8. (iv) アクセス許可の追加と管理者の同意
- アプリがアクセスできる機能を制御するために、アプリの権限を付与する
- 権限付与には、「検索してアクセス許可の追加」と「管理者の同意を与える」が必要
- 具体的には、アプリの登録からアプリを開き、APIのアクセス許可から「アクセス許可の追加」ボタンを押下
- Microsoft Graph -> アプリケーションの許可 -> (ii)で調べたアクセス許可をもとに検索、「アクセス許可の追加」を押下
- XXXXに管理者の同意を与えますを押下
9. (v) クライアントシークレットを作成
- アプリの登録からアプリを開き、証明書とシークレットから「新しいクライアントシークレット」を押下する
- 注意点
- 有効期限が存在するため、有効期限の管理が必要
- クライアントシークレットは、生成時しかコピーできないため、必ずコピーする
項目 | 名称 |
---|---|
アプリケーション名 | [application name] |
クライアントID | [clientid] |
クライアントシークレット | [secret] |
アクセス権 | DeviceManagementServiceConfig.Read.All, DeviceManagementServiceConfig.ReadWrite.All |
10. (vi) Powershellの雛形を更新し、動作を確認する
-
基本メソッド
-
Get-AuthToken-Secret
-
Tenantid, Clientid, ClientSecretからリクエストヘッダを生成
-
Invoke-GraphMethod
- Header, Bodyを指定してGraphAPIにGet/Post -
追加メソッド
-
Get-CorporateDeviceIdentifiers
-
企業用デバイスの一覧を取得
-
Set-CorporateDeviceIdentifiers
-
企業用デバイスを登録
スクリプト雛形
Function Get-AuthToken-Secret(){
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true)]
$tenantId,
[Parameter(Mandatory=$true)]
$clientId,
[Parameter(Mandatory=$true)]
$clientSecret
)
$tokenRequestUri = "https://login.microsoftonline.com/{0}/oauth2/token" -f $tenantId
$header = @{
"Content-Type" = "application/x-www-form-urlencoded"
}
$body = @{
"grant_type" = "client_credentials"
"client_id" = $clientId
"client_secret" = $clientSecret
"resource" = "https://graph.microsoft.com”
}
$accessToken = (Invoke-WebRequest -Method "POST" -Uri $tokenRequestUri -Headers $header -Body $body).Content | ConvertFrom-Json
$authHeader = @{
'Content-Type'='application/json'
'Authorization'="Bearer " + $accessToken.access_token
'ExpiresOn'=$accessToken.expires_on
}
$authHeader
}
Function Invoke-GraphMethod(){
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true,ParameterSetName="GET")]
[Switch]
$GET,
[Parameter(Mandatory=$true,ParameterSetName="POST")]
[Switch]
$POST,
[Parameter(Mandatory=$true)]
[String]
$graphApiVersion,
[Parameter(Mandatory=$true)]
[String]
$resource,
[Parameter(Mandatory=$true)]
$authToken,
[Parameter(Mandatory=$false,ParameterSetName="GET")]
[Parameter(Mandatory=$true,ParameterSetName="POST")]
[String]
$body
)
try{
if($GET){
$uri = "https://graph.microsoft.com/$graphApiVersion/$($resource)"
(Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).value
}
if($POST){
$uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)"
(Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Body $body -Headers $authToken).value
}
}catch{
$_
}
}
スクリプト更新(追加後)
Function Get-AuthToken-Secret(){
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true)]
$tenantId,
[Parameter(Mandatory=$true)]
$clientId,
[Parameter(Mandatory=$true)]
$clientSecret
)
$tokenRequestUri = "https://login.microsoftonline.com/{0}/oauth2/token" -f $tenantId
$header = @{
"Content-Type" = "application/x-www-form-urlencoded"
}
$body = @{
"grant_type" = "client_credentials"
"client_id" = $clientId
"client_secret" = $clientSecret
"resource" = "https://graph.microsoft.com”
}
$accessToken = (Invoke-WebRequest -Method "POST" -Uri $tokenRequestUri -Headers $header -Body $body).Content | ConvertFrom-Json
$authHeader = @{
'Content-Type'='application/json'
'Authorization'="Bearer " + $accessToken.access_token
'ExpiresOn'=$accessToken.expires_on
}
$authHeader
}
Function Invoke-GraphMethod(){
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true,ParameterSetName="GET")]
[Switch]
$GET,
[Parameter(Mandatory=$true,ParameterSetName="POST")]
[Switch]
$POST,
[Parameter(Mandatory=$true)]
[String]
$graphApiVersion,
[Parameter(Mandatory=$true)]
[String]
$resource,
[Parameter(Mandatory=$true)]
$authToken,
[Parameter(Mandatory=$false,ParameterSetName="GET")]
[Parameter(Mandatory=$true,ParameterSetName="POST")]
[String]
$body
)
try{
if($GET){
$uri = "https://graph.microsoft.com/$graphApiVersion/$($resource)"
(Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).value
}
if($POST){
$uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)"
(Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Body $body -Headers $authToken).value
}
}catch{
$_
}
}
Function Get-CorporateDeviceIdentifiers(){
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true)]
$authToken,
[Parameter(Mandatory=$false)]
$deviceIdentifiers
)
$graphApiVersion = "beta"
try{
if($DeviceIdentifier){
$Resource = "deviceManagement/importedDeviceIdentities?`$filter=contains(importedDeviceIdentifier,'$DeviceIdentifier')"
}
else {
$Resource = "deviceManagement/importedDeviceIdentities"
}
Invoke-GraphMethod -GET -graphApiVersion $graphApiVersion -authToken $authToken -resource $Resource
}catch{
$_
}
}
Function Set-CorporateDeviceIdentifiers(){
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true)]
[ValidateSet("imei","serialNumber")]
$deviceIdentifierType,
[Parameter(Mandatory=$true)]
[ValidateSet("false","true")]
$overwriteDeviceIdentities,
[Parameter(Mandatory=$true)]
$deviceIdentifier,
[Parameter(Mandatory=$false)]
$description,
[Parameter(Mandatory=$true)]
$authToken
)
$graphApiVersion = "beta"
$Resource = "deviceManagement/importedDeviceIdentities/importDeviceIdentityList"
try{
$body = @"
{
"overwriteImportedDeviceIdentities": $overwriteDeviceIdentities,
"importedDeviceIdentities": [ {
"importedDeviceIdentifier": "$deviceIdentifier",
"importedDeviceIdentityType": "$deviceIdentifierType",
"description": "$description"}]
}
"@
if($deviceIdentifierType -eq "imei" -and ($deviceIdentifier -notmatch "^[0-9]+$" -or $deviceIdentifier.length -lt 15)){
throw "imei format is invalid"
}
if($deviceIdentifierType -eq "serialNumber" -and $deviceIdentifier -notmatch "^[a-zA-Z0-9]+$"){
throw "serial format is invalid"
}
Invoke-GraphMethod -POST -graphApiVersion $graphApiVersion -body $body -authToken $authToken -resource $Resource
}catch{
$_
}
}
$tenantId = "<TENANTID>"
$clientId = "<CLIENTID>"
$clientSecret = "<CLIENT_SECRET>"
$deviceID = "<DEVICEID>"
$deviceDescription = "<DEVICE_DESCRIPTION>"
$authToken = Get-AuthToken-Secret -tenantId $tenantId -clientId $clientId -clientSecret $clientSecret
$deviceList = @(Get-CorporateDeviceIdentifiers -authToken $authToken )
$deviceList
$authToken = Get-AuthToken-Secret -tenantId $tenantId -clientId $clientId -clientSecret $clientSecret
Set-CorporateDeviceIdentifiers -authToken $authToken -deviceIdentifierType serialNumber -overwriteDeviceIdentities false -deviceIdentifier $deviceID -description $deviceDescription
11. アクセス許可でエラーが出た時には...
- 適切にアクセス許可を設定した場合でも、以下の通り、エラーが出る場合がある。
- その場合には、エラー時に必要なアクセス許可が出てくるので、それを設定して再度試してみよう。
Line |
XXX | (Invoke-RestMethod -Uri $uri -Method Post -ContentType "appli …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"error":{"code":"Forbidden","message":"{\r\n \"_version\": 3,\r\n \"Message\": \"Application is not authorized to perform this operation.
| Application must have one of the following scopes: DeviceManagementServiceConfiguration.ReadWrite.All,
| DeviceManagementServiceConfig.ReadWrite.All - Operation ID (for customer support): 00000000-0000-0000-0000-000000000000 - Activity ID:
| xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - Url:
| https://fef.msuc02.manage.microsoft.com/DeviceEnrollmentFE_2111/StatelessDeviceEnrollmentFEService/deviceManagement/importedDeviceIdentities/microsoft.management.services.api.importDeviceIdentityList?api-version=xxxx-xx-xx\",\r\n \"CustomApiErrorPhrase\": \"\",\r\n \"RetryAfter\": null,\r\n \"ErrorSourceService\": \"\",\r\n \"HttpHeaders\": \"{}\"\r\n}","innerError":{"date":"yyyy-mm-ddThh:mm:1ss","request-id":"xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxxx","client-request-id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}}}
12. まとめ
- Azureのアプリ登録からアクセス権限の設定、テストまでの手順が整備できた
- 今後、こちらの記事を参考に作成してみたいと思う