GASでJamf Pro API
考え方とか書き方とか、自分用にメモするぞ。
答えだけ欲しい人はついてこれる内容なのかわからないぞ。
謝辞
本当にありがとうございます!
めっちゃ勉強になった!!
頑張ってnote書いてみるけど、まとまるか?
今回やりたいこと
GASでJamf Pro APIを叩きたい。
Classic APIじゃない方使いたい。
最終的にはPC稼働ログを取ってきたい、と思ったけど、そこは別のサービス使えば良いかもしんない。まあ、とにかくAPIを叩くぞ。
参考記事がfor文で処理時間掛かるから改変したい気もする。
まずはAPI叩けるところまで。
参考
今回のコード(GitHub)
https://github.com/ymgcmnk/JamfProAPI_FromGAS
まずBasic認証を通して、トークンを取得し、毎回リフレッシュめんどくさいからエンドポイントとなるAPI呼び出しの関数を実行した時にリフレッシュトークンを取得する仕組み。
考え方・作成手順
最終的なことはコード見ていただければ、多分だいたい分かる、はず、伝わって、お願い。しかし、そこに至るまでは、あれこれ苦戦があったので記してみます。
1. リファレンス読む
で、上記のコードに至るまでには、いろいろなリファレンスを読む必要があった。
手始めに、2018年のものでちょっと古いが、こちらの日本語のJamf Blogに目を通してみた。
Classic API 使用時の7つのポイント
まずは Jamf Developer Portal (https://developer.jamf.com) をご覧くださいってことなのでご覧になりますわよ。
なんか色々書いてあるけど、JAmfProをポチー。
で、「Classic API」と「Jamf Pro API」の二種類があるわけですよ。なんとなく新しいの使った方がいいような気がしますが、ここでスクロールしてちょっと書いてあることを読んでみます。
JSONもサポートしてて、OAthなJamf Pro APIでやっぱりいいような気がします。この辺、教えて詳しい人!!
そんなわけで、Jamf Pro APIを見てみます。
Getting Staeted と Overviewを斜め読みにして、必要そうな情報を探します。APIを叩くにはとにかくにも認証だよねってことで、OAthとかAuthentication っぽいところを探します。
と、認証の前に、リファレンス見ると最終的なAPIとしては例えばこれが良さそうかなー。
クエリパラメータをセットすると、左側の黒いところ、CURLにクエリ入りのURLが出てくる。便利。
各種言語対応。つっても、GASはこれコピペしただけじゃ動かんからね、参考程度に。
話を認証の話に戻します。
Overview の Authentication and Authorization です。
https://developer.jamf.com/jamf-pro/docs/jamf-pro-api-overview
最初のパラグラフで、ユーザアカウントかグループ使うから必要なprivileges(権限、特権)付けといて的なこと言ってます(適当な大意)
Slack API使うときに、App作ってそれにスコープ付ける的な感じですね。
この件はこちらのブログでも言及されていました。
https://tech.visasq.com/getworktimefromjamf/
必要以上の権限をつけると危ないので、今回の目的であればcomputerのReadだけでいいですね。
ユーザアカウントはJamf Proの管理コンソールからどうにかしてください。
で、認証の流れです。
Basic認証使って、リクエストを送ってね
こんな感じのレスポンスを受け取るよ
そのレスポンスのトークン使ってね
的なこと言ってます。
なので、まずはBasic認証を通し、トークンをゲットし、それを使ってAPIを通じてGETする、という流れ。
が、ここで注意。
そう、デフォルトでは、トークンは30分で有効期限が切れるんである。
で、keep-aliveを使って、前回有効だったトークンを使って、また新しいトークンを作る、ってことになる。
あと、Getting Started のここ。
Example Codeには認証ヘッダー情報ないから追加してね、と。
https://developer.jamf.com/jamf-pro/reference/post_v1-auth-token
2. Jamf Pro管理コンソールからユーザアカウント作成
こちらのブログの「補足:実行するJamfアカウントの権限について」にある通り。
https://tech.visasq.com/getworktimefromjamf/
3.Basic認証
認証の流れ、おさらいです。
Basic認証使って、リクエストを送ってね
こんな感じのレスポンスを受け取るよ
そのレスポンスのトークン使ってね
まずはBasic認証でトークンを取得するところをやっていきます。
GASでさあどうするってことで考えます。
https://developer.jamf.com/jamf-pro/docs/jamf-pro-api-overview
から、レシピを開いてみる。
ここで curlconverterの出番です。コピーした部分をコンバータにかけます。
https://curlconverter.com/javascript
お、よく見る感じになってきた。
これをもとに整えていきます。
説明すっ飛ばしますが、コードはこうなりました。
function getTokenViaBasicAuth() {
const url = PropertiesService.getScriptProperties().getProperty("url")
const username = PropertiesService.getScriptProperties().getProperty("username")
const password = PropertiesService.getScriptProperties().getProperty("password")
// ClassicAPIはBasic認証なのでCredentialをBase64エンコードする
// username:passwordはAPIアクセス用のJamfアカウントを作成し指定する
const auth_data = Utilities.base64Encode(`${username}:${password}`)
const response = UrlFetchApp.fetch(url + 'auth/token',
{
method: 'POST',
headers: { 'Authorization': 'Basic ' + auth_data } //Basicのあとは半角スペース必要
});
const obj = JSON.parse(response.getContentText())
const token = obj.token
PropertiesService.getScriptProperties().setProperty("token", token)
const test = PropertiesService.getScriptProperties().getProperty("token")
console.log(test)
}
先ほどのレシピを見てみます。
これと、コンバータを組み合わせて、GAS用に整えた、という感じです。
btoaは削除して良かったんですが、ここちょっとよくわかってない。
この初代トークンを、次のリフレッシュトークンに利用するため、最後にプロパティストアに格納しています。
3.Basic認証で取得したトークンを使ってAPI、でも30分でexpireするからkeep-alive を噛ます
書き捨てのコードだったら、例えば下記のコードの token_value に Basic認証で取得したコードをそのまま直書きすればよいわけです。
/**
* https://developer.jamf.com/jamf-pro/reference/get_v1-computers-inventory
*/
function getComputersInventory() {
const token_value = tokenRefresh()
const url = PropertiesService.getScriptProperties().getProperty("url")
const response = UrlFetchApp.fetch(url + '/computers-inventory?section=GENERAL&page=0&page-size=100&sort=id%3Aasc',
{
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token_value, //Bearerのあとは半角スペース必要
'Accept': 'application/json'
}
});
const obj = JSON.parse(response.getContentText())
console.log(obj)
}
しかし、まあ、あれよ、ね。いちいち、またBasic認証してコード書いてって面倒じゃん。
そういうわけで、トークンリフレッシュ用のコードを用意します。
/**
* tokenRefresh
* @return {string} newToken
*/
function tokenRefresh() {
const token_value = PropertiesService.getScriptProperties().getProperty("token")
const url = PropertiesService.getScriptProperties().getProperty("url")
// console.log(url)
// return
const response = UrlFetchApp.fetch(url + 'auth/keep-alive',
{
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token_value,
'Accept': 'application/json'
}
//Bearerのあとは半角スペース必要
});
const obj = JSON.parse(response.getContentText())
const newToken = obj.token
PropertiesService.getScriptProperties().setProperty("token", newToken)
console.log(newToken)
return newToken
}
さっきのBasic認証とほぼ同じ構造です。
ベースURLの後ろが違うです。
新しいトークンをまたプロパティストアに上書き格納です。
4.エンドポイントAPI
先に紹介してしまいましたが、最終的にはこのコードでAPI経由して情報を取得します。
/**
* https://developer.jamf.com/jamf-pro/reference/get_v1-computers-inventory
*/
function getComputersInventory() {
const token_value = tokenRefresh()
const url = PropertiesService.getScriptProperties().getProperty("url")
const response = UrlFetchApp.fetch(url + '/computers-inventory?section=GENERAL&page=0&page-size=100&sort=id%3Aasc',
{
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token_value, //Bearerのあとは半角スペース必要
'Accept': 'application/json'
}
});
const obj = JSON.parse(response.getContentText())
console.log(obj)
}
上記は https://developer.jamf.com/jamf-pro/reference/get_v1-computers-inventory を参考にしています。
const response = UrlFetchApp.fetch(url + '/computers-inventory?section=GENERAL&page=0&page-size=100&sort=id%3Aasc'
この部分は、リファレンスのクエリパラメータでウニョウニョしてお好みのものにしてください。
はー、これで、とりあえず取れました。やったー!
コーヒーメソッドとハマリポイント
コーヒーメソッドとは
なんかうまくいかない時、再読み込みする時、再起動する時、そんな時にはコーヒーを淹れて人間をリフレッシュしよう。トークンのリフレッシュ(再取得)が必要なように、人間にもリフレッシュが必要なのだ。
By そーちゃん
https://twitter.com/black777cat
ハマりポイント
今回コード書いてて、あーってなったところ。
・GASが重い、実行したあと、そのままになる。→たいていなんかコードが間違ってるのでコーヒーメソッドを投入。
・http / https
httpsが正解。
・プロパティストアに格納してる値が間違ってる
特にベースURL。/が余計だったり、足りなかったり。
あと、コピペ間違いで https://yourserver.jamfcloud.com とそのまま入れてたり。
うーん、あとは閉じカッコなかったり余計だったり、よくあるやつ…
curl
curlをうまく扱えるようになりたひ。
curlでBasic認証はこう
curl -s -u username:password https://yourserver.jamfcloud.com/api/v1/auth/token -X POST
curl -h でオプションの説明みるとこう。
-s, --silent Silent mode
-u, --user user:password Server user and password
ここに書いてある通りですやね。
""が要るの?要らないの?って毎回思ってしまう。]
で、これを応用して、
こことか
ここ
をみながら、やってみたけど上手くいかなかった。
curl -s -H "Authorization: Bearer XXXXXXX" -H 'Accept: application/json' -u 'https://yourserver.jamfcloud.com/api/v1/computers-inventory?section=null&page=0&page-size=200&sort=id%3Aasc' -X GET
ではない?
もう寝ろってことだな。
今後の課題
認証よくわかってない。
Postmanよくわかってない。
ロジックの組み立て弱い。
curlわからん。
余談
海外のまとめサイト的なものに載った、のか?
参考URLまとめ
curlを各種言語に変換してくれる優れもの。
https://curlconverter.com/
GAS BASIC認証をパスしてJSONをPOSTする方法
https://admin-it.xyz/gas/gas-basicauth/
Basic認証、Digest認証、Bearer認証、OAuth認証方式について
https://architecting.hateblo.jp/entry/2020/03/27/130535
JamfでPC稼働時間を集計する
Jamfで勤怠の稼働時間を取得して労務課題を解決する!
Jamf Pro の API を調べてみました
配列の中にオブジェクトが入っている場合のvalue値の取得方法二次元配列 Javascript
https://qiita.com/shuichi0712/items/cf966ad8bae9e610ea32
curlコマンドのきほんと使用例
https://maasaablog.com/curl/2648/
Mac/Windowsで起動やシャットダウン、スリープオン/オフの時間を調べる方法
https://komoriss.com/how-to-check-reboot-shutdown-sleep-on-off-time/
https://freeelover.com/
#JamfProAPI
#JamfPro
#GAS
#ペアプロ
#ノンプロ研