この記事はレコチョク Advent Calendar 2022 の3日目の記事となります。
https://qiita.com/advent-calendar/2022/recochoku
Jamf Pro のグループに期限付きでユーザを入れたい。1
動機
レコチョクでは Mac や iPhone、iPad といった Apple 製品を Jamf Pro で管理しています。
Jamf Pro には「グループ」という仕組みがあり、グループに含まれるすべてのユーザに対して一様にライセンス等を割り当てることができます。
期限的にライセンスを割り当てる場合は、期限の開始日と終了日にグループを管理する作業が求められます。
具体的には、12月5日(開始日)から12月8日(終了日)まで、あるユーザをグループに入れてライセンスを割り当てたいとすると、12月5日の朝にグループに追加する作業が発生し、12月8日の夜にグループから削除する作業が発生することになります。
これらの操作を自動化することで、管理者の省力化とオペレーションミス削減を図りたいと考えました。
方針
グループには「スマートグループ」と「スタティックグループ」の2種類が存在します。
それぞれのグループを利用した方法を検証します。
- 方法1 – スマートグループを用いた方法
ユーザの拡張属性に開始日と終了日を事前に入力しておき、開始日になると自動的にグループに追加され、終了日を過ぎると自動的にグループから削除されるようにします。 -
方法2 – スタティックグループを用いた方法
開始日と終了日をリストとして事前に作成しておき、Jamf Pro API と Classic API を活用してグループを自動管理します。
方法1
ここではスマートグループを用いた方法を考えます。
Step 1. 開始日と終了日を入力するための拡張属性を作成する
クライテリアで日付比較をするため、データタイプは
Date にします。
Step 2. スマートグループを作成する
クライテリアは以下のように設定します。
AND/OR | クライテリア | オペレータ | 値 | ||
---|---|---|---|---|---|
▼ | テスト開始日 | more than x days ago | 1 | ▼ | |
and ▼ | ▼ | テスト終了日 | less than x days ago | 1 | ▼ |
Step 3. 拡張属性に開始日と終了日を入力する
ここでのポイントは以下2点です。
- クライテリアを満たすため、開始日と終了日の日付は想定の1日前(24時間前)です。
- JST ではなく UTC なので、開始日と終了日の時刻は想定の9時間前です。
つまり、想定する日時の 33 (=24+9) 時間前を設定しておく必要があります。
例えば「2022年12月3日 00時00分00秒」にグループに入ってほしいのであれば、設定する日時は33時間前の「2022年12月1日 15時00分00秒」です。
方法1の課題点
- 拡張属性に入力する日時は前日かつ UTC であるため、設定ミスが発生する恐れがある。
- 開始日・終了日には対応する一組しか設定することができない。
- スマートグループが再計算されるタイミングや周期は Jamf Pro 依存であるため、いつグループに追加・削除されるのか分からない。2
- 対象のスマートグループのみを強制的に再計算するため、Jamf API の recalculate を定期的に実行することを推奨します。
https://developer.jamf.com/jamf-pro/reference/post_v1-smart-user-groups-id-recalculate
方法2
ここではスタティックグループを用いた方法を考えます。
Step 1. スタティックグループを作成する
特別な設定は必要ありません。
Step 2. グループの追加・削除リストを作成する
今回は3列のみのシンプルな CSV ファイル(list.csv)を作成します。
- USER_ID (対象ユーザの ID)
- START_DATE (開始日)
- END_DATE (終了日)
USER_ID,START_DATE,END_DATE 1,20221201,20221202 2,20221202,20221205 |
Step 3. 追加・削除リストを読み込む
Step 2. で作成した CSV のリストをスクリプトから読み込みます。
const csv = parse(fs.readFileSync("list.csv"), { columns: true }); |
Step 4. Jamf API からトークンを取得する
https://developer.jamf.com/jamf-pro/reference/post_v1-auth-token
JAMF_ID と
JAMF_PASSWORD は適切な権限があるユーザの ID とパスワードを使います。
(Jamf Pro のログインに普段使っているユーザではなく、権限を限定したスクリプト用ユーザを推奨します)
const auth = Buffer.from(`${JAMF_ID}:${JAMF_PASSWORD}`).toString("base64"); const headers = { Authorization: `Basic ${auth}` }; const response = await axios.post( `https://yourserver.jamfcloud.com/api/v1/auth/token`, {}, { headers } ); const token = response.data.token; |
Step 5. スタティックグループに現在含まれるユーザを取得する
ユーザの取得には Classic API を使います。
GROUP_ID には Step 1. で作成したスタティックグループの ID を使用します。
https://developer.jamf.com/jamf-pro/reference/findusergroupsbyid
const headers = { Authorization: `Bearer ${token}` }; const response = await axios.get( `https://yourserver.jamfcloud.com/JSSResource/usergroups/id/${GROUP_ID}`, { headers } ); const users = response.data.user_group.users; |
Step 6. スタティックグループに追加するユーザを抽出する
CSV から以下の条件を満たしているユーザを抽出します。
- 本日( TODAY)が CSV の START_DATE と END_DATE の間に含まれている
- まだスタティックグループに存在していない
const includeArray = csv .filter((x) => x.START_DATE <= TODAY && TODAY <= x.END_DATE) .map((x) => x.USER_ID); const deduplicatedIncludeArray = [...new Set(includeArray)]; const addArray = []; deduplicatedIncludeArray.forEach((x) => { let exists = false; users.forEach((y) => { if (!exists && x === String(y.id)) { exists = true; } }); if (!exists) { addArray.push(x); } }); |
Step 7. ユーザを追加するための XML を作成する
let xml = `<user_group> <user_additions>`; addArray.forEach((x) => { xml += ` <user> <id>${x}</id> </user>`; }); xml += ` </user_additions> </user_group>`; |
Step 8. ユーザをスタティックグループに追加する
Step 7. で作成した XML を Classic API に PUT します。
https://developer.jamf.com/jamf-pro/reference/updateusergroupsbyid
const headers = { Authorization: `Bearer ${token}`, "Content-Type": "text/xml", }; const response = await axios.put( `https://yourserver.jamfcloud.com/JSSResource/usergroups/id/${GROUP_ID}`, xml, { headers } ); |
以上でスタティックグループへのユーザ追加は完了です。
次に、期限が過ぎたユーザをスタティックグループから削除します。
Step 9. ユーザをスタティックグループから削除する
処理の流れは追加のときと同様のため、詳細な説明は割愛します。
CSV のすべての行で以下を満たしているユーザを削除します。
- 本日( TODAY)が CSV の START_DATE と END_DATE の間に含まれていない
- すでにスタティックグループに存在している
サンプルコードを示しておきます(jamf)。
方法2の課題点
- スクリプトを作成する必要があり、メンテナンスには API の知識が求められる。
- スクリプトを定期実行するサーバを維持しなければいけない。
- リストを Google Sheets、スクリプトを Google Apps Script で作成し、トリガーを一日一回の実行にするといいかも。
- 運用を続けていくうちにリストが大きくなれば、パフォーマンスにも気を配る必要がある。
- 定期的に棚卸しを実施し、不必要な行は削除する。
まとめ
本稿では Jamf Pro のグループに期限付きでユーザを入れる方法について考察しました。
それぞれの方法に課題点がありますので、状況に応じて適切な方法を選択していきたいと思います。
Azure AD に関しては、拙稿「Azure AD の動的グループに期限付きでユーザーを入れたい」も合わせてご覧ください。
https://qiita.com/sndyhg/items/1f0eebc73b822d92f5dc
明日のレコチョク Advent Calendar 2022 は4日目、「【Android】初学者の私が1ヶ月で学んだ内容」 です。