Jamf Pro の API Client をつくったので、ポリシーの一覧を取得した

※ この note は日記に近いです。技術的な情報はあまり多くありません。

以前 GitHub Actions でシェルスクリプトを動かして Jamf Pro にスクリプトを自動デプロイする検証をしたのですが、スクリプトだけではなくポリシーもデプロイできるようにしたいと思い、準備を進めています。

管理する設定が増えたり複数のメンバーで運用するフェーズになると、 Jamf Pro のダッシュボードでカジュアルに変更できる状況は、構成管理・変更管理の面で気になってきます。

Jamf Pro (Classic) API の Go クライアント

シェルスクリプトだけで実現するのはさすがに力技感があるので、 Go でデプロイ用のスクリプトを書いています。書いているうちに「これは Jamf Pro の API クライアントを作った方が効率が良さそう」と、ちょこちょこ実装していました。

現時点で実装できている機能は「ポリシー」と「スクリプト」の取得、作成、更新、削除で、とりあえずコードで管理したかった部分がカバーできました。ちゃんとリファクタリングをしてから note を書こうと思っていたら、いつまで経っても出せそうになかったので、これからちゃんと仕上げるんだぞ!と背水の陣の気持ちで公開します。

原型は 4 月にはできていたのですが、時がたって見直すと全然中身がわからん状態でした。。ちょうど LayerX さんが freee API の Go クライアントを公開されていたので「こうやって書けばいいのか!」と参考にさせていただきました。ありがとうございます!!

GitHub -> Jamf Pro へのデプロイ用スクリプトも原型はできているので、動作確認ができたら公開しようと思っています。

Jamf Pro の API

Jamf Pro の API は Classic API, Jamf Pro API の 2 種類があります。

それぞれ以下のように説明されており、 Classic API の方が安定版であるように読めました。

The Classic API is the primary resource for programmatically interacting with Jamf Pro. The base URL for the Classic API is located at /JSSResource on each Jamf Pro instance. Documentation and “Try it out” features are built into each instance of Jamf Pro, and can be accessed at /api.
The Jamf Pro API is now available for production usage! While the majority of endpoints are ready for consumer adoption, endpoints that include the term "preview" in their path or tag are subject to future changes.

実際、ポリシーの操作は Jamf Classic API でのみ提供されていたため、今回作成した API クライアントでは以下のとおり使い分けています。
- ポリシーの操作 -> Classic API
- スクリプトの操作 -> Jamf Pro API

Classic API は Content Type: XML の仕様となっており、初めて Go の xml パッケージを使いました。 JSON も使えると嬉しいです。
※ 正確には、 GET の場合は JOSN で返してもらうことができるのですが、POST, PUT 時は XML でデータを渡す必要があり、レスポンスも XML です。


Jamf Pro のポリシーを取得してみた

せっかく API クライアントをつくったので、 Jamf Pro に登録済みのポリシーと、ポリシーに紐づいているスクリプトのパラメタを取得するスクリプトを書いて動かしてみました。各ポリシー・スクリプトのパラメタを YAML 形式でファイルに出力します。

出力された YAML たちを見てちょっと感動したのですが、でも何かの情報が不足している。。 Postman でレスポンスを確認したところ、公開されている Jamf Classic API のリファレンス (2021/06/16 時点) には載っていない XML の要素がありました。

// GET: /policies/id/{id}

~
 </account_maintenance>
 <reboot>
   <message>This computer will restart in 5 minutes. Please save anything you are working on and log out by choosing Log Out from the bottom of the Apple menu.</message>
   <startup_disk>Current Startup Disk</startup_disk>
   <specify_startup/>
   <no_user_logged_in>Do not restart</no_user_logged_in>
   <user_logged_in>Do not restart</user_logged_in>
   <minutes_until_reboot>5</minutes_until_reboot>
   <start_reboot_timer_immediately>false</start_reboot_timer_immediately>
   <file_vault_2_reboot>false</file_vault_2_reboot>
 </reboot>
 <maintenance>
~

<reboot> タグはおそらく Restart Options (再起動オプション) の情報で、これがリファレンスには載っていないため、情報を更新していただけないか Jamf サポートチームにお願い中です。


と、さも自作ツールで気づいたかのように書きましたが、実際は DataDog さんが公開している API クライアントを見ていて気づいたものです。

policy_entity.go のなかでポリシーの構造体が定義されており、 RebootSettings というフィールドが用意されています。

// policy_entity.go

type PolicyContents struct {
	XMLName              xml.Name                  `json:"-" xml:"policy,omitempty"`
	General              *PolicyGeneral            `json:"general" xml:"general,omitempty"`
	Scope                *Scope                    `json:"scope" xml:"scope,omitempty"`
	SelfServices         *SelfService              `json:"self_service" xml:"self_service,omitempty"`
	PackageConfiguration *Packages                 `json:"package_configuration" xml:"package_configuration,omitempty"`
	ScriptCount          int                       `json:"-"  xml:"scripts>size,omitempty"`
	Scripts              []*PolicyScriptAssignment `json:"scripts" xml:"scripts>script,omitempty"`
	Printers             interface{}               `json:"printers" xml:"printers,omitempty"`
	DockItems            []*DockItem               `json:"dock_items" xml:"dock_items,omitempty"`
	AccountMaintenance   *PolicyAccountMaintenance `json:"account_maintenance" xml:"account_maintenance,omitempty"`
	RebootSettings       *PolicyRebootSettings     `json:"reboot" xml:"reboot,omitempty"`
	Maintenance          *PolicyMaintenance        `json:"maintenance" xml:"maintenance,omitempty"`
	FilesProcesses       *PolicyFileProcesses      `json:"files_processes" xml:"files_processes,omitempty"`
	UserInteraction      *PolicyUserInteraction    `json:"user_interaction" xml:"user_interaction,omitempty"`
	DiskEncryption       *PolicyDiskEncryption     `json:"disk_encryption" xml:"disk_encryption,omitempty"`
}

Datadog さんの API クライアントがかなり仕上がっているようなので、最初からこちらを使わせていただくのが良かったのでは・・・という気持ちもある反面、自分で作ってみたという経験と、エラーが起きても自力で対処できるだけの理解度が得られたのでヨシ!!ということにしたいと思います。


最後に。 API リファレンスを読んでいて、 Jamf Pro の機能の豊富さを改めて認識しました。夢が広がりますね。

いただいたサポートは記事を書くためのエネルギー(珈琲、甘いもの)に変えさせていただきます!