cfgutil : iOSをコマンドラインで設定するネタ

# これは何か

Apple Configurator 2のコマンド版

## インストール方法
App StoreからApple Configurator 2をインストール。
起動してメニューの「Apple Configurator 2」から「自動化ツールをインストール」を選択
あとはターミナルで任意のディレクトリで。

## SSHで実行するときは追加コマンドが必要

```shell-session
$ sudo /bin/launchctl asuser 0 cfgutil list
```

## cfgutilのヘルプと独断と偏見に満ちた意訳とコメント

cfgutil 2.15.1 (811)

割と必ずエラーを吐くが気にしない。というよりも誰か対処法求む。
とりあえず「2> /dev/null」で誤魔化す。

```text:cfgutil
% cfgutil 
objc[42373]: Class AMSupportURLConnectionDelegate is implemented in both /usr/lib/libamsupport.dylib (0x20c70b640) and /Library/Apple/System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x1019ec2c8). One of the two will be used. Which one is undefined.
（中略）
cfgutil 2.15.1 (811)

Global options:
	[-C | --certificate] <argument>
	Path to DER-encoded certificate of supervising organization.

	[-K | --private-key] <argument>
	Path to DER-encoded private key of supervising organization.

	[-e | --ecid] <argument>
	Device to act on, by ECID. Can be used more than once.

	[-f | --foreach]
	Act on all selected devices.

	--format <argument>
	Output format. (text, JSON, plist)

	--progress
	Show steps/progress even without plaintext output.

	--timeout <argument>
	Set the timeout for detecting connected devices. (in seconds)

	[-v | --verbose]
	Increase the logging verbosity.

Commands:
	activate
		Activate attached devices.
	add-tags
		Add tags to devices.
	backup
		Take a backup of a prepared iOS device.
	clear-passcode
		Clear passcode on a device. (supervised only)
	erase | erase-content
		Erase content and settings on devices. (supervised only)
	exec
		Run a script when devices attach or detach.
	get | get-property
		Show various properties of a device.
	get-app-icon
		Save app icons from a device.
	get-icon-layout
		Fetch the home screen layout from a device.
	get-unlock-token
		Get unlock tokens from supervised devices.
	help | usage
		Show help for a command or show all commands.
	install-app | install-application | install-applications | install-apps
		Install apps on attached devices.
	install-doc | install-docs | install-document | install-documents
		Install documents on attached devices.
	install-profile | install-profiles
		Install profiles on attached devices.
	list | list-devices
		List attached devices.
	list-backups
		List backups stored on the host.
	pair
		Try to pair with attached devices.
	prepare
		Initial configuration of freshly erased devices.
	remove-app
		Remove apps from attached devices.
	remove-profile
		Remove profiles from attached devices.
	remove-tags
		Remove tags from attached devices.
	rename | set-name
		Set the name on a device.
	restart
		Reboot attached devices. (supervised only)
	restore | update
		Install the latest System version on devices.
	restore-backup
		Restore a backup to an iOS device.
	revive
		Attempt to revive a device from recovery mode.
	set-backup-password
		Set or remove backup passwords on attached devices.
	set-icon-layout
		Set home screen icon layout on devices.
	set-wallpaper | wallpaper
		Set background image on devices. (supervised only)
	shut-down
		Power off attached devices. (supervised only)
	syslog
		Print a running output of the device's syslog.
	unpair
		Remove pairing between the host Mac and device.
	version
		Show this program's version.
```

### Global Option　の一部

全体に係る設定

「cfgutil」の直後に指定する。「cfgutil --format json get all」のように。

「-C」と「-K」はSupervisor　Mode（以下、監視モード）のデバイスに対して、組織識別情報の秘密鍵と証明書を指定する。
これを指定しないと使えないコマンドがあったり、コマンドの挙動が変わる。

「-e」と「-f」はコマンドを適用するデバイスの指定。
「-e」はECIDを指定して一台、「-f」は接続中の全台を対象とする。「-e」を複数指定できるかは知らん。
~~後述の「exec」の際は「-f」指定は危険。たぶん。~~ 「-e」と合わせてたぶん無意味。

「--format」は結果出力のフォーマット。
たぶん「get」の時ぐらいしか使い道がない。「get」の結果をJSONで吐き出してパースして処理すれば、デバイス情報の一覧化やスクリプトでの判定処理に使える。


### activate iOSデバイスのアクティベート

文字通り、iOSのアクティベートをする。
単体で通信できない状況のデバイスを、何も設定はしないがとりあえず使えるようにする時ぐらいしか使い道が思いつかない。
通常、設定アシスタントの割と最初の方でWi-Fiに繋ぐかモバイル通信を利用するかを選ばないと先へ進めない。
だが、アクティベートしておくと「モバイル通信を利用」は出ず、Wi-Fiに繋がなくても「次へ」を押せるようになり、オフラインのままホーム画面まで進められる。

なお、これをやらなくても、Apple Configuratorやcfgutilの操作の割と多くがアクティベーションもついでにやってしまうので、ほんとこれ単体で使うシーンは思いつかない。


### add-tags デバイスにタグを付与

Apple Configurator上で管理するタグをつける。
定期的にApple Configuratorに繋ぎ直すような運用をしない限り使い道が思いつかない。
たぶん、このタグはApple Configurator系以外では見ることができない。
PCに記録されるのか、デバイスに書き込まれるか（≒別のPCで見れるのか）は不明だがgetで取れる。

スクリプトで自動化する際の端末状態判定に使えるかも知れない。
その場合、タグ文字列の他、タグのUUIDをきちんと設定しておいた方が良さげ。

### backup デバイスのバックアップを取得

iTunesやFinderで取るとの同じように、ローカルストレージにデバイスのバックアップを取得する。
おそらく、iTunes・Finderと異なり、インストールしたApp Storeのアプリ状況（何がインストールされていたか）はバックアップ対象外（これでとったバックアップから復元しても、アプリの再インストールが走らない。手動でインストールしたらデータは復活しているっぽいんで、アプリデータはバックアップ対象

### clear-passcode パスコードを消去

画面ロック解除のパスコードを忘れた際に、パスコードをすっ飛ばしてパスコード設定無し状態にする。
監視モードである必要があり、かつ事前に「get-unlock-token」でパスコード解除用のトークンを取得しておかなければならないっぽい。
ついでに、トークンに有効期限があるようで、定期的に取っておかないといけないくさい。

定期的に回収してApple Configuratorで管理しており、MDMがないとか、予備の手段としてやるぐらいか。

### erase 全てのコンテンツと設定をリセット

デバイスを初期化する。
監視モードが必要。とあるが、ロック解除されていれば通っている気がしないでもない。
これで初期化する場合はアクティベーションロックの解除はされない。

### exec デバイスの接続時または接続解除時にスクリプトを実行

スクリプトファイルとアクション（接続時か解除時か）を指定して実行すると待機状態となり、設定したアクション時にスクリプトを実行する。
うまく使えば便利だが、安定して使えるスクリプトを書くのが面倒くさい。

コマンドオプションは「exec」コマンドの後ろに記述する。
「cfgutil exec -a　script.sh」で接続時、「cfgutil exec -d script.sh」で接続解除時な感じ。
スクリプトは「chmod +x」とかで実行権限の付与が必要。ないと「Permission denied」と怒られる。

スクリプトを呼び出す際に、以下の変数が設定される。

- ECID: 
    - デバイスのECID
    - スクリプト内でcfgutilを呼び出す時は原則「cfgutil -e $ECID」とすることになる
- PATH: 
    - 環境変数のものに「/usr/local/bin」を先頭に付与（移動）させた状態になるっぽい
- UDID
    - デバイスのUDID
    - パケットキャプチャをとるようなexecを組む時ぐらいか？
        - 接続時に「rvictl -s $UDID」、でもgetを使うスクリプト組む方が使いやすい気がする
- deviceName: 
    - デバイス名、デフォルトで「iPhone」とか「iPad」になってるアレ
- deviceType: 
    - デバイスの内部型式（というのか？）、「iPhone 13」に対する「iPhone14,5」な名称のやつ
- buildVersion: 
    - インストールされているOSのビルド番号
    - 「設定」→「一般」→「システムバージョン」をタップすると表示されるやつ
    - 「iOS 15.5」に対する「19F77」みたいなの
- firmwareVersion: 
    - OSのバージョン、「15.5」とか
- locationID
    - デバイスが接続されているUSBポート番号
    - macの「システム情報」→「USB」→「デバイス」を選択した中にある「場所ID」

これ以外のデバイス固有情報は、後述の「get」で取得するような感じ。

bashやzshのスクリプトが叩けるので、Apple Configuratrのブループリントでは難しい「条件に応じた動作」を仕込むことができる。

- バージョンが最新でなければ、アップデートする
- 初期化されていない状態であれば初期化する
- 電話番号の一部をデバイスの名前にする
- 電話番号やIMEIを基準にプロファイルや壁紙を変える
- バッテリー残量が一定以上になるまで待つ

とか、まあそんな感じ

長くなるのでいつか別にまとめたい

「Ignores --foreach and --ecid global options.」　と、これらのグローバルオプションは効かないとされている。
が、スクリプトで呼び出した先のcfgutilにまでこれが及ぶかが不明で、まだ試してもいないが、スクリプト内では「-e $ECID」を付けておいた方がいいかもしれない。何となくそんな予感がする。

なお、execを実行した時点で既に接続済みのデバイスにはattachが走る。こわい。

### get デバイスの情報を取得

「cfgutil get xxx」で情報を取得する。
「xxx」に「all」とすれば、取れる情報を全部とる。

個別にとるのは、とるたびにそこそこ時間がかかるので、allで取ったものを変数やファイルとして持っておいてパースすると早い。（バッテリー残量とか、変動するものを除いて）

グローバルオプションの「--format」で、JSONかplist（xml）を指定して出しておけばたぶん加工抽出は容易
CSVには対応していないので、Apple Configuratorのデバイス情報出力みたいなことをやりたい場合はJSONやXMLから加工する処理を入れないとならない。

でも、execと組み合わせて繋いでいくだけでデバイス情報が取れていくので、トータルでは楽かもしれない

### get-app-icon　アプリアイコン取得

接続したデバイスの、指定したアプリのアイコン画像を取得する。
画質が悪いのでApp Storeから取得する方が遥かに良い。
何のために存在しているのかわからない。

### get-icon-layout　ホーム画面のアイコン配置状態を出力

「set-icon-layout」でアイコン配列をする際のネタ取得用

### get-unlock-token パスコードクリア用のトークンを取得

そのまんま。
保存先はApple Supportのどっかに書いてあった。

### install-app ipaファイルのアプリケーションをインストール

「install-application」「install-applications」「install-apps」でもいいらしい。
ipaファイルを指定してインストールする。
主に検証用AdHocアプリのインストール用か。In Houseアプリは絶滅危惧種だし、MDM使えばいいし。

### install-doc アプリにファイルを保存

指定したアプリに、指定したファイルを書き込む。
対応しているアプリでないと意味がない。
例えば、教育機関のデバイスであれば教科書アプリに教科書データを書き込む手段として「iTunesから入れる」という手段が用意されているのであれば使えなくもない。が、使えるアプリなんて片手で数えるほどしか見たことがない。

### install-profile プロファイルをインストール

指定したプロファイルをデバイスにインストールする。
監視モードのデバイスである場合、組織識別情報を指定しないとサイレントインストールとならないため注意が必要。
逆に、サイレントインストールできないプロファイル（一部設定は手入力するように作ったプロファイル）は組織識別情報の引数を消すだけで良いので、Apple Configuratorに比べて汎用性があるような気がする。

### list 接続デバイス一覧表示

接続されているデバイスを表示する。
表示される内容は「exec」で設定される変数とだいたい同じ。個人的に必要な情報が出ないのでほぼ使わない。

### list-backups　バックアップデータの一覧表示

Apple Configurator、Finder、cfgutilでとったバックアップデータの一覧を表示する。

### pair　ペアリング再試行

接続したデバイスとのペアリングを再試行する。
デバイス側であやまって「信頼しない」を選んだ際に、これを使えば再度ダイアログが出てくる・・・時と出てこない時があるので抜き差しした方が早く、ほぼ使わない

### prepare デバイスを準備

Apple Configuratorの「準備」に相当

組織識別情報はDERフォーマットの証明書を指定する。
細かい仕様が不明なので、大人しくApple Configuratorで作った組織識別情報をエクスポートするか、どうしても手作りするのであればそれに倣ったほうが無難

### remove-app アプリをアンインストール

パッケージ識別子で指定する。アプリデータも消しているっぽい。

### remove-profile 　プロファイルをアンインストール

指定した識別子、または指定したローカルのプロファイルと同じ識別子のプロファイルをデバイスから削除する。

### remove-tags　タグを削除

指定したUUIDのタグを削除する。タグ名ではないことに注意。

### rename デバイスの名前を変更

set-name でも良いっぽい。
コマンドではApple Configuratorがあらかじめ用意している変数は用いれないが、シェルなのできちんとやれば柔軟な名づけが可能。割と使える。

### restart デバイスを再起動

そのまんま

### restore 復元

AppleConfiguratorの「復元」に相当。基本は「OS最新化＋初期化」
引数でipswを指定できる。

updateの方は未確認

### restore-backup バックアップから復元

バックアップ復元用のパスワードは引数で指定。
どのバックアップを戻すかの指定は、バックアップ名もしくはバックアップディレクトリパスを指定。

### revive デバイスの復活

アップデート失敗とかで、いわゆるリンゴループに陥った時とかに使う。
ユーザーデータを保持したまま、最新のOSをインストールする。既に最新であっても再インストールする。
復活率は経験的に高くない。

### set-backup-password 暗号化バックアップの設定・解除

「--remove」オプションで暗号化バックアップを解除する

### set-icon-layout アイコン配置を設定する

「get-icon-layout」で取ったアイコン配置データを読み込み、配置を設定する。
実態はJSONなので手書きできなくもない。

配置データにあり、デバイスにないアプリの場合、「-f」オプションの指定が必要。インストール後に配置が変わる。（一回限り）
配置データになく、デバイスにあるアプリの場合、配置データの末にアプリ名昇順で並ぶ。

ウィジェットの情報は含まれず、「ホーム画面から削除」としたものは設定ファイルに含まれず、設定ファイルに含まれないものは上記の通りホーム画面に出てきてしまうので使いづらくなった（iOS15.5時点）

### set-wallpaper 壁紙を設定

オプションでロック時かロック解除時を指定。
Apple Configuratorにある、文字列を埋め込む機能はないので、必要なら別途画像を生成するようなスクリプトを組んで画像に文字を埋め込む。Imagemagickとか。

### Shut-down デバイスをシャットダウン

そのまんま。
設定作業の最後に入れておけば少し楽。監視モードであれば。

### syslog デバイスログを表示

### unpair ペアリング解除

ペアリングを解除する。
デバイスが設定アシスタントの状態である時は即座にペアリングし直されることに注意。
また、監視モードのデバイスである場合は、組織識別情報を持っていればペアリング済みになる様子。

# 余談

[automatorも使えるようになるけど](https://configautomation.com/prepare.html)使いづらかった。
なお上記以外にも機能はあるので、一覧は引数無しでcfgutilを実行。

他のツールを含め、大量に設定をしなければいけない場合は、Apple Configuratorだけでなく、cfgutilを噛ませたスクリプトを利用する方が良いパターンもありそう。ただ組める人がどこにどんだけおんねんという課題。

# 追伸

上記コマンド例について、Supervisor化した端末に対してコマンドを実施する場合はグローバルオプションで組織識別情報の指定が必要な場合があり。「```cfgutil -K supervisor.key -C supervisor.der ～```」てな感じで。
逆にこれを指定しない方がいい場合もあり。対話型インストールが必要なプロファイルとか。