
はじめに
こんにちわ、ヤスムラです。
先日、以下の記事でGemini Canvasを使ったツール作成を紹介しましたが、今回はその時にGeminiさんに作成してもらった「Intuneのデバイス登録をSlackに通知するツール」の完成版スクリプトと設定方法を紹介したいと思います。
事前準備
設定には、以下のアカウント(権限)が必要です。
項目 | 実施すること |
Microsoft Entra の管理者権限 | API連携用のアプリ登録と権限付与 |
Slackの管理者権限 | 通知用Webhookの追加 |
Googleアカウント | GASの実行 |
設定手順
手順は以下の5ステップです。
- 手順①:Microsoft Entraにアプリケーション登録
- 手順②:Slackアプリの追加
- 手順③:GASのコード入力
- 手順④:GASへ設定値を入力
- 手順⑤:初回実行とトリガーの設定
手順①:Microsoft Entra にアプリケーション登録
Intuneの情報へアクセスするための「アプリケーション」を登録します。
1. Microsoft Entra管理センター にサインイン
2. 左メニューの [ID] > [アプリケーション] > [アプリの登録] >[+ 新規登録] をクリック

3. 以下のように入力し [登録] をクリック

項目 | 内容 |
名前 | わかりやすい名前 (Intune Slack Notifier など) |
サポートされているアカウントの種類 | この組織のディレクトリ内のアカウントのみ |
リダイレクト URI: | 空のまま |
4.登録完了後、概要ページで以下の2つの値をコピーして控えておいて下さい。

- アプリケーション (クライアント) ID
- ディレクトリ (テナント) ID
5. 左メニューから [管理] > [証明書とシークレット] > [+ 新しいクライアントシークレット] をクリック

6. 説明を入力し、有効期限を選択して [追加] をクリック
7. 作成したシークレットの値をコピーして控えておいて下さい。

8. 左メニューから [API のアクセス許可] > [+ アクセス許可の追加] をクリック

9. [Microsoft Graph] > [アプリケーションの許可] をクリック
10. 検索ボックスに DeviceManagementManagedDevices.Read.All
と入力
11. 表示された権限にチェックを入れ、[アクセス許可の追加] をクリック

12.構成されたアクセス許可にて[(テナント名)に管理者の同意を与えます]をクリック

13. 状態に✅マークが表示されていることを確認
手順②:Slackアプリの追加
Slackへ通知するためのWebhook URLを取得します。
1. Slack APIのアプリ管理ページで [Create New App] > [From scratch] を選択

2.アプリ名と対象ワークスペースを選択し [Create App] をクリック

3. [Incoming Webhooks] をクリックし、機能を有効(On)にする

4. [Add New Webhook] をクリックして通知チャンネルを選択し[許可する] をクリック
5. 生成された Webhook URL (https://hooks.slack.com/...
) をコピーして控えておいて下さい。
手順③:GASのコード入力
GASプロジェクトを作成し、スクリプトを貼り付けます。
- Google Apps Scriptで「新しいプロジェクト」を作成
- プロジェクト名にわかりやすい名前を設定「Intune Slack通知など」
- 初期コードを全て削除し、以下のコードを貼り付けて保存
/**
* Microsoft Intuneに登録された新しいデバイスを検知し、Slackに通知するGoogle Apps Script。
*/
// --- 設定はスクリプトプロパティで行います ---
// (設定項目は変更ありません)
//
// SLACK_WEBHOOK_URL : SlackのIncoming Webhook URL
// AZURE_CLIENT_ID : Azure AD アプリケーション (クライアント) ID
// AZURE_CLIENT_SECRET : Azure AD クライアントシークレット
// AZURE_TENANT_ID : Azure AD ディレクトリ (テナント) ID
// ------------------------------------------A
// スクリプトプロパティに前回実行時間を保存するためのキー
const PROPERTY_KEY_LAST_CHECK_TIME = 'LAST_CHECK_TIME_ISO';
/**
* アプリケーション認証を使い、Microsoft Graph APIのアクセストークンを取得します。
*/
function getAccessToken(config) {
const tokenUrl = `https://login.microsoftonline.com/${config.azureTenantId}/oauth2/v2.0/token`;
const payload = {
'grant_type': 'client_credentials',
'client_id': config.azureClientId,
'client_secret': config.azureClientSecret,
'scope': 'https://graph.microsoft.com/.default'
};
const options = {
'method': 'post',
'payload': payload,
'muteHttpExceptions': true
};
try {
const response = UrlFetchApp.fetch(tokenUrl, options);
const result = JSON.parse(response.getContentText());
if (response.getResponseCode() !== 200) {
console.error('アクセストークンの取得に失敗しました。', result);
return null;
}
return result.access_token;
} catch (e) {
console.error('アクセストークン取得中に例外が発生しました。', e);
return null;
}
}
/**
* メインの処理を実行する関数。
*/
function checkNewDevices() {
const scriptProperties = PropertiesService.getScriptProperties();
const config = {
slackWebhookUrl: scriptProperties.getProperty('SLACK_WEBHOOK_URL'),
azureClientId: scriptProperties.getProperty('AZURE_CLIENT_ID'),
azureClientSecret: scriptProperties.getProperty('AZURE_CLIENT_SECRET'),
azureTenantId: scriptProperties.getProperty('AZURE_TENANT_ID')
};
// 設定値のチェック
for (const key in config) {
if (!config[key] && key !== 'slackWebhookUrl') { // slackWebhookUrlは通知時にのみ必須
console.error(`スクリプトプロパティ「${key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`).toUpperCase()}」が設定されていません。`);
return;
}
}
// 毎回新しいアクセストークンを取得
const accessToken = getAccessToken(config);
if (!accessToken) {
console.error('処理を中断しました: アクセストークンが取得できませんでした。');
return;
}
// --- 以下、時間ベースのチェックロジック---
const executionTime = new Date();
const executionTimeISO = executionTime.toISOString();
const lastCheckTimeISO = scriptProperties.getProperty(PROPERTY_KEY_LAST_CHECK_TIME);
if (!lastCheckTimeISO) {
scriptProperties.setProperty(PROPERTY_KEY_LAST_CHECK_TIME, executionTimeISO);
console.log('初回実行のため、基準時間を設定しました。次回から新規デバイスのチェックを開始します。基準時間:', executionTimeISO);
return;
}
try {
const lastCheckTime = new Date(lastCheckTimeISO);
console.log(`チェックを開始します。対象期間: ${lastCheckTimeISO} 以降`);
const url = 'https://graph.microsoft.com/v1.0/deviceManagement/managedDevices';
const response = UrlFetchApp.fetch(url, {
headers: { 'Authorization': `Bearer ${accessToken}` },
muteHttpExceptions: true
});
const result = JSON.parse(response.getContentText());
if (response.getResponseCode() !== 200) {
console.error('Graph APIからのデバイスリスト取得に失敗しました。', result);
return;
}
const allDevices = result.value;
if (!allDevices || allDevices.length === 0) {
console.log('Intuneに登録されているデバイスはありませんでした。');
scriptProperties.setProperty(PROPERTY_KEY_LAST_CHECK_TIME, executionTimeISO);
return;
}
const newDevices = allDevices.filter(device => {
const enrolledDateTime = new Date(device.enrolledDateTime);
return enrolledDateTime > lastCheckTime;
});
if (newDevices.length > 0) {
console.log(`${newDevices.length}件の新しいデバイスが見つかりました。`);
newDevices.forEach(device => {
sendSlackNotification(device, config.slackWebhookUrl);
});
} else {
console.log('新しいデバイスは見つかりませんでした。');
}
scriptProperties.setProperty(PROPERTY_KEY_LAST_CHECK_TIME, executionTimeISO);
console.log('チェック完了。次回の基準時間を更新しました:', executionTimeISO);
} catch (e) {
console.error('スクリプトの実行中にエラーが発生しました。', e);
}
}
/**
* 指定されたデバイス情報をSlackに通知します。
*/
function sendSlackNotification(device, webhookUrl) {
if (!webhookUrl) {
console.error('Slack Webhook URLが設定されていません。通知をスキップします。');
return;
}
const enrolledDateTimeJST = new Date(device.enrolledDateTime).toLocaleString('ja-JP');
const message = {
text: `新しいデバイスがIntuneに登録されました: ${device.deviceName}`,
blocks: [
{
type: 'header',
text: { 'type': 'plain_text', 'text': ':computer: 新規デバイス登録通知', 'emoji': true }
},
{
type: 'section',
fields: [
{ 'type': 'mrkdwn', 'text': `*デバイス名:*\n${device.deviceName}` },
{ 'type': 'mrkdwn', 'text': `*所有者:*\n${device.managedDeviceOwnerType}` },
{ 'type': 'mrkdwn', 'text': `*登録日時:*\n${enrolledDateTimeJST}` },
{ 'type': 'mrkdwn', 'text': `*ユーザー:*\n${device.userPrincipalName || 'N/A'}` },
{ 'type': 'mrkdwn', 'text': `*OS:*\n${device.operatingSystem || 'N/A'}` },
{ 'type': 'mrkdwn', 'text': `*機種名:*\n${device.model || 'N/A'}` },
{ 'type': 'mrkdwn', 'text': `*シリアル番号:*\n${device.serialNumber || 'N/A'}` }
]
},
{ 'type': 'divider' },
{
'type': 'context',
'elements': [
{ 'type': 'mrkdwn', 'text': `デバイスID: ${device.id}` }
]
}
]
};
const options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(message),
'muteHttpExceptions': true
};
UrlFetchApp.fetch(webhookUrl, options);
}
/**
* スクリプトを定期実行するためのトリガーを設定します。
*/
function setTrigger() {
const triggers = ScriptApp.getProjectTriggers();
triggers.forEach(trigger => {
if (trigger.getHandlerFunction() === 'checkNewDevices') {
ScriptApp.deleteTrigger(trigger);
}
});
ScriptApp.newTrigger('checkNewDevices')
.timeBased()
.everyHours(1)
.create();
console.log('1時間ごとの定期実行トリガーを設定しました。');
}
/**
* 基準時間をリセットします。(デバッグ用)
*/
function resetLastCheckTime() {
PropertiesService.getScriptProperties().deleteProperty(PROPERTY_KEY_LAST_CHECK_TIME);
console.log('基準時間をリセットしました。');
}
手順④:GASへ設定値を入力
手順①と②で取得した情報をGASのスクリプトプロパティに設定します。
1. GASエディタで [プロジェクトの設定] (⚙️アイコン) をクリック
2. [スクリプト プロパティ] セクションで [スクリプト プロパティを追加] をクリック
3.以下の4つの情報を追加

プロパティ (Property) | 値 (Value) |
AZURE_CLIENT_ID | 手順①で取得したクライアントID |
AZURE_CLIENT_SECRET | 手順①で取得したクライアントシークレット |
AZURE_TENANT_ID | 手順①で取得したテナントID |
SLACK_WEBHOOK_URL | 手順②で取得したSlackのWebhook URL |
手順⑤:初回実行とトリガーの設定
スクリプトを実行して初回実行日時の取得と自動実行のトリガーを設定します。
1. GASエディタで checkNewDevices
関数を選択し、[▷ 実行]
2. (初回のみ)権限の承認ポップアップが表示されるので[権限を確認]をクリックして許可

3.ログに以下メッセージが表示されることを確認

4.setTrigger
関数を選択して [▷ 実行]
5.ログに「1時間ごとの定期実行トリガーを設定しました。」と表示されれば全設定が完了です。

動作確認
すべての設定が完了し、ツールが正常に動作すると、Intuneに新しいデバイスが登録された際に、以下のような通知がSlackへ自動で届きます。

補足
- 初回実行の役割: 手順⑤で最初に
checkNewDevices
を実行すると、その実行時刻が「基準時間」としてスクリプトプロパティに記録されます。スクリプトは2回目以降の実行で、この記録された時間よりも後に登録されたデバイスを「新規」と判断します。 - 過去登録したデバイスを通知したい: テスト等で過去のデバイスを再度通知させたい場合は、GASのスクリプトプロパティにて「LAST_CHECK_TIME_ISO」に登録されている時間を手動修正すれば実施可能です。
さいごに
今回は、Intuneの新規デバイス登録をGASでSlackへ自動通知する仕組みを紹介しました。
この設定で日々の確認作業が不要になり、デバイス登録をより効率的に把握できます。業務効率化の一助となれば幸いです。
さいごに当方は副業情シスとして、中小企業様を中心に社内ITの最適化をご支援しております。もし、「社内にIT担当者がいなくて困っている」「今のIT環境、もっと良くできるはず…」といったお悩みを抱える企業様がいらっしゃいましたら、ぜひお声がけください。下記サイトに詳細を記載しておりますので、ご興味をお持ちいただけましたら、問い合わせページよりお気軽にご連絡いただけますと幸いです。
コメント