😽

Jamf Pro APIを利用して、PC資産リストを作成する

2021/06/20に公開2

はじめに

JamfProに登録しているMacの情報を、「GoogleAppsScript(以下、GAS)」を利用して「Jamf Pro API」を叩き、Googleスプレッドシートに出力する記事です。

背景

弊社ではWindowsをGoogleMDM(GCPW)、MACはJamfProで端末管理しているため、
PC一覧を確認する際、CSVなどでDL→スプレッドシートに追記、細かいデータは手作業で更新する必要がありました。
大変面倒くさいですし、資産管理ツールを導入するのもコストが掛かるので、GASを利用して
自動的にPC一覧表を更新してくれる仕組みを作りました。

参考としたもの

Jamf Pro API
https://www.jamf.com/developers/apis/jamf-pro/overview/
GoogleとJamfProのLDAP連携
https://docs.jamf.com/ja/10.26.0/jamf-pro/administrator-guide/クラウドアイデンティティプロバイダとの統合.html
JmafProAPIを使うきっかけとなった良記事です。
https://tech.visasq.com/getworktimefromjamf/

やったこと

1.GoogleとのLADP連携
LDAP連携をする事で、User&LocationにGoogleで設定した”氏名”と”メールアドレス”が登録されるため、誰が利用しているのか判別出来るようになります。
※設定方法はJamfがマニュアルを公開しているので、ここでは記載しません。
2.PCインベントリを転記させるスプレッドシートを用意し、GASを書きます
実行すると下図の様にスプレッドシートに出力されます。
今回は、PCのホスト名と誰が所持しているか、Jamfへの最終接続日だけ知りたかったので、これだけですが、JamfProのコンピュータ>インベントリにある情報は持ってこれます。

GASコード

const API_URL = 'https://"company-url"/uapi/auth/tokens'
const API_URL_INVENTORY = 'https://"company-url"/api/v1/computers-inventory?section=GENERAL&section=USER_AND_LOCATION'
const spreadsheet_id = SpreadsheetApp.openById('スプレッドシートID');//スプレッドシートID格納
const sheet_name = spreadsheet_id.getSheetByName('シート名');//シート名を格納

//JAMF PRO APIへアクセスするためのTokenを取得
function tokenget() {
  try{
  const auth_data = Utilities.base64Encode('jamf_ID:jamf_PW');//JamfProトークン呼び出しのためのID,PW
  var options = {
    'method' : 'POST',
    'contentType': 'application/json',
    'headers': {'Authorization' : 'Basic ' + auth_data,'accept' : 'application/json'},
  };

 const response = UrlFetchApp.fetch(API_URL, options).getContentText();//レスポンス情報を格納
  const response_data = JSON.parse(response);//JSON形式に整形

  pc_inventory(response_data.token);//PC情報出力関数をコール

  }catch(e){
    console.error("エラー:", e.message);
    console.log(options);
  }
}

function pc_inventory(token_data){
  let last_contact = "";
  try{
    //sheet_name//データ初期化
    sheet_name.clear();
    var values = [];
    values.push(["ID", "PC", "LoginID", "LastContactDay","Name", "MailData"]);
    sheet_name.getRange(1,1,1,6).setValues(values);
    const FValues = sheet_name.getRange('A:A').getValues();  //A列の値を全て取得
    const LastRow = FValues.filter(String).length;  //空白の要素を除いた長さを取得 ※1行目に値が入ってないとエラーになる

  var _options = {
    'method' : 'GET',
    'contentType': 'application/json',
    'headers': {'Authorization' : 'Bearer ' + token_data,'accept' : 'application/json'},
  };

    const _response = UrlFetchApp.fetch(API_URL_INVENTORY, _options).getContentText();//Jamfへインベントリ情報をコールしてデータを格納
    const _response_data = JSON.parse(_response);//JSON形式に整形

    //データ転記(PC個数分、ループを回す)
    for(var j = 0; j < _response_data.totalCount; j++){
      sheet_name.getRange('A'+(LastRow+1+j)).setValue(_response_data.results[j].id);//JamfPro ID番号
      sheet_name.getRange('B'+(LastRow+1+j)).setValue(_response_data.results[j].general.name);//PC名
      sheet_name.getRange('C'+(LastRow+1+j)).setValue(_response_data.results[j].general.mdmCapable.capableUsers);//loginUser名
      last_contact = Utilities.formatDate(new Date(_response_data.results[j].general.lastContactTime),"Asia/Tokyo", "yyyy/MM/dd");//lastContactTimeの文字列を日付の値へ変換し、YYMMDD形式へ整形
      sheet_name.getRange('D'+(LastRow+1+j)).setValue(last_contact);//JamfProへ最後に接続した時間
      sheet_name.getRange('E'+(LastRow+1+j)).setValue(_response_data.results[j].userAndLocation.realname);//Googleのユーザ名
      sheet_name.getRange('F'+(LastRow+1+j)).setValue(_response_data.results[j].userAndLocation.email);//Googleのメールアドレス
    }
  }catch(e){
    console.error("エラー:", e.message);
    console.log(_options);
  }
}

※API_URL_INVENTORYに格納したURLは、JamfProのリファレンスページで自作できます。凄い。
※「company-url」、「スプレッドシートID」、「シート名」、「jamf_ID:jamf_PW」については現環境の値を入力してください
※全コードから対象箇所を抜き出しているため、余計な変数が残っているかもしれません。見つけても無視してください。

所感

・Jamf Pro APIは最初にtokenを発行すれば、一回のトリガーで様々な関数を呼び込む事が出来るので、複数のAPIを組み合わせて使えて便利。

Discussion

yoshioyoshio

大変参考になる記事ありがとうございました!

こちら、GASのquota的に負担が少ない書き方で一部試しました。
可読性は若干落ちますが、カラムが追加されても変数とpushを追加するだけで、getRangeの箇所の変更も不要になります。

    for (var j = 0; j < _responseData.totalCount; j++) {
      const id = _responseData.results[j].id;
      const name = _responseData.results[j].general.name;
      const capableUsers = _responseData.results[j].general.mdmCapable.capableUsers;
      const lastContact = Utilities.formatDate(new Date(_responseData.results[j].general.lastContactTime), "Asia/Tokyo", "yyyy/MM/dd");
      const realName = _responseData.results[j].userAndLocation.realname;
      const email = _responseData.results[j].userAndLocation.email;
      values.push([id,name,capableUsers,lastContact,realName,email]);
    }
   sheetName.getRange(1,1,values.length,values[0].length).setValues(values);
tiripiritiripiri

コメントありがとうございます!参考になります!!