コーポレートグループITチームのみともりです。今回はJamf初心者なりにAPIを使って色々頑張ってみたお話となります。
背景
リモートワークが当たり前の現在ですが、みなさん自宅で仕事をしていると辞め時が分からなくなってつい遅くまで仕事をしちゃうことってないですか?
会社としては、長時間労働が社員の健康に悪影響を及ぼすことを防ぐために、労働時間を正確に把握し、しかるべき対策を行う必要があるのですが、オフィスに出社してカードをピッとやるわけではないので、例えば勤怠システムで退勤の打刻をしてからサービス残業したとしても把握ができないわけです。
そこで労働時間を正確に把握するために、各企業ではPCの稼働時間を実際の労働時間と見なして、それを計測するために様々なソリューションを導入しています。
Jmaf Proでできるんじゃ?
弊社でも類に漏れず、今まではDeskTimeというトラッキングツールを全PCにインストールしていたんですが、「メンテナンスが辛い&コストがかかる」ということで、最近やっと導入できたJamf Proでなんとか集計できないかな?と思って試してみることにしました。
※Jamf ProとはApple製品のデバイス管理のためのプロダクトです。
Application Usage Logs
ということで調べてみると、Jamfはアプリケーションの使用状況を日々集計してくれているじゃないですか。強い。
正直なところ「精度はそれなりなんでしょ?」と思っていたのですが、DeskTimeと比較したところ1日で誤差は10分程度。これは使える。ということで、CSVでダウンロードできないかなーと色んなところを触ってみましたが、間違ってログを消してしまうという悲劇が起こっただけでした。
Jamf Pro Classic API
やっぱりAPIです。CSVダウンロードなんて平成に置いてきましょう。
調べたところ、以下のAPIでApplication Usageが取得できるようです。Basic認証とのことですが大丈夫でしょう。
https://www.jamf.com/developers/apis/classic/reference/#/computerapplicationusage
Google Apps Script
最終的にスプレッドシートに集計しようと思っていたので、集計処理はGASにお任せすることにしました。ちなみに、さも他にも選択肢があるような言い方してますがGASしか使えません。
補足として、Jamfの全コンピューター一覧はこちらのAPIから取得してます。
https://www.jamf.com/developers/apis/classic/reference/#/computers
const API_URL = 'https://xxxx.jamfcloud.com/JSSResource/'
function findWorkaholic() {
// 前月初日から前月末日までを集計
var start_date = new Date();
start_date.setMonth(start_date.getMonth()-1);
start_date.setDate(1);
var end_date = new Date();
end_date.setDate(0); // 0を指定すると前月末日になる
var year = start_date.getFullYear();
var month = ("0"+(start_date.getMonth() + 1)).slice(-2); // 0埋めで2桁に合わせる
// YYYY-MM-DD_YYYY-MM-DD
var search_range = year + '-' + month + '-' + ('0' + start_date.getDate()).slice(-2) + '_' + year + '-' + month + '-' + ('0' + end_date.getDate()).slice(-2);
// 記録用のスプレッドーシートを開き新しくシートを作成する
const ss = SpreadsheetApp.openById([スプレッドシートのID]);
var sheet = ss.insertSheet(year + '-' + month);
var values = new Array();
values.push(['PC Name', 'Date', 'Usage(min)']); // First Row
// ClassicAPIはBasic認証なのでCredentialをBase64エンコードする
// username:passwordはAPIアクセス用のJamfアカウントを作成し指定する
const auth_data = Utilities.base64Encode('username:password');
var options = {
'method' : 'GET',
'contentType': 'application/json',
'headers': {'Authorization' : 'Basic ' + auth_data,
'accept' : 'application/json'},
};
// 全てのコンピューター一覧を取得
const response = UrlFetchApp.fetch(API_URL + 'computers', options);
var cont = JSON.parse(response.getContentText('UTF-8'));
for (var i=0; i<cont.computers.length; i++) {
var computer = cont.computers[i];
// 対象のコンピューターの一か月のアプリ使用状況を取得
const _response = UrlFetchApp.fetch(API_URL + 'computerapplicationusage/id/' + computer.id + '/' + search_range, options);
var _cont = JSON.parse(_response.getContentText('UTF-8'));
// アプリがforeground(アクティブ状態)だった時間を集計する
var time = 0 // 月ごとに集計したい場合
for (var j=0; j<_cont.computer_application_usage.length; j++) {
var day_usage = _cont.computer_application_usage[j];
//var time = 0; // 日ごとに集計したい場合
for (var k=0; k<day_usage.apps.length; k++) {
time += day_usage.apps[k].foreground;
}
//values.push([computer.name, day_usage.date, time]); // 日ごとに集計したい場合
}
values.push([computer.name, year + '-' + month, time]); // 月ごとに集計したい場合
}
// 結果をスプレッドシートに保存
sheet.getRange(1, 1, values.length, 3).setValues(values);
return;
}
上のコードでは一か月の合計を集計してますが、1日毎の時間を集計したかったらコメントを切り替えてください。
実行結果
おおお!いい感じ!あとは端末名と使用者の紐づけをすればバッチリですね。Dateと書いてあるのに年月しか入っていないのは気にしないでください。
ちなみに無操作時も稼働時間として集計してしまうので、スリープ無効にして四六時中稼働しっぱなしの端末がいるととんでもない稼働時間になります。でもそんなことするのはごく少数なのであまり考えないことにします。
恒例のことですが、分かりやすさを重視してエラー処理を省いたり認証情報をハードコードしたりしているので、本番稼働させる場合はそのあたりは考慮して頂ければと思います。
補足:実行するJamfアカウントの権限について
ここで注意点があるのですが、Jamf APIを実行するユーザーはフル権限を持ったユーザーを絶対に使わないようにしましょう。 認証情報が漏洩する可能性はゼロではないですし、今回のようにBasic認証の場合はHTTPSに乗っかるとはいえ平文なのでリスクがさらに高くなります。
JmafユーザーのPrivilegeはカスタマイズできますので、万が一漏洩したときのリスクを下げるため、最低限の権限だけをつけるようにしましょう。(今回はComputersのReadしかつけていない)
感想
Jamfはやっぱりすごい。
色んなサービスを使っているとUIのアップデートがあったりして使いこなすのが大変なので、どれか一つのツールで完結できると運用がとても楽になります。
Jamfは本当にいろんなことが実現できるので、JamfでできることはJamfに寄せたほうが幸せになると思いました。というかJamfを使いこなすのが大変ですしJumpStartは決して安くはないので、もしJmafを導入している会社はしっかり使い倒しましょう。