わりとどうでもいい序章
企業における業務用スマホや逸般の誤家庭において、Wi-Fi、VPN、Webサイトの接続認証にクライアント証明書を用いた運用はそれなりに行われているものと考えられる。
クライアント証明書配布について嘆く
ほんとどうでもいい駄文
金と手間をいとわない場合、IntuneやWSOなど主に洋物EMMとPKI基盤を連携させ、EMMを解してクライアント証明書の管理しているだろう。
この場合、一般的にはEMMとPKI基板間が連携し、最終的にはEMMからiOSデバイスへ証明書プロファイルの形でクライアント証明書が配信される。
なお、この場合のPKI基板はADCSだったりSCEP、ACMEといった汎用プロトコル、各PKIのAPIであったりする。
メリットとしては、きちんと設定すればクライアント証明書の発行・配布・失効をきちんと管理できる。
デメリットとしては、冒頭の通り金と手間がかかること、そして何よりEMMが対応していないと当然ながらできないことである。
個人的にこれまでいくつかのEMM/MDMをとりあえず触る機会があったのだが、この機能を持つEMMはとりあえずライセンスが高い。そして高機能であるがために、習熟するにも設定を行うにしても時間がかかる。
そして、言い方が難しいが安価なMDM、国産MDMに関しては機能が絞られている分最低限のデバイス管理には苦労しないのであるが、クライアント証明書配信の機能が省かれていたり、外部基板連携が無いことが多い。
PKCS12形式(p12、pfxファイル)をZIPで固め、パスワードを記述したテキストファイルとともにアップロードし、ファイル名ベースで配信先デバイスを指定することで個別にクライアント証明書を配布する機能を持つMDMがあったりする。機能があるだけありがたいのではあるが、セキュリティ面や運用面を考えるとこれに依存することは好ましくないと思ったりする。もちろん、更新や失効は手動でつらい。
余談ではあるが、iOS18(2024年)まではAES暗号化されたPKCS12を扱えず、3DES方式でなければならなかった。ADCSでクライアント証明書の一括エクスポートを模索して、やっとできたと思ったらiOSでインポートできなかったときは泣いた。当時あまり情報がなかったもの。
この機能すらない場合、とれる手段はWebサイトやメールによる直接配布か、管理者が(≒ステージング、キッティングで)手動で一台ずつインストールして回るかになる。
前者は利用者がぱーぷーであればクライアント証明書の漏洩(指定外デバイスへのインストールや、他者への流用)が起きるだろうし、後者は場合によっては(NDAとかがあったとしても)生の証明書をごっそり外部へ渡す羽目になる。もちろん更新や失効はまたこれ考えないといけなくてつらい。
というわけで、iOS16からACMEを用いる機能が実装されている。
構成プロファイルを配布する機能であれば、だいたいどのMDMにもあるので、iOSでのACME直証明書要求を試してみたかったけど気が付けば数年放置していたので試してみたってだけの記事である。
iOSにはSCEPによる証明書要求する機能もだいぶ前からあったが、ACMEを選択した理由としては、秘密鍵にECCを用いることがでることと、生成と保管にSecure Enclaveを用いることができるっぽいってあたり。
まず結論
正直、ACMEペイロードを用いてiOSデバイスから直接ACMEで証明書を取得することは現時点では現実的ではないと判断。
まず、Apple device-attest-01 challengeに対応した真っ当なベンダーが存在しないって話。
今回試したstep-caはこれに対応しており、結果としてiOSデバイスに対してクライアント証明書を発行することはできたが、これをメインに運用するのはつらい。扱いきれていないのもあるけどいろいろと機能不足。
とくに、後述の設定のみでは正規のiOSデバイスからであれば要求に応えてしまう。
step-caでここらを捌こうとした場合、テンプレを作りこんだり、何か仕組みを考えにゃならぬ。
iOSデバイスから直接要求ではなく、EMMを介在させてEMMから認証局に発行要求することは、デバイスの認証や検証をEMMがある程度補えている部分でもある。きちんとクライアント証明書を管理したいのであば、その機能を持ったEMMを利用した方が最終的には管理者が幸せになれる。
step-caで直接iOS
環境
Ubuntu 24.04.03
docker-ce 28.5.1
smmallstep/step-ca
要点
今回これらのコマンドは、稼働させたコンテナに入り込んでstepコマンドを実行
- step-caにACMEのprovisionerを追加する
- DOCKER_STEPCA_INIT_ACME 変数でもいい
- デフォルトの証明書有効期限が24hなので伸ばす
- iOSの仕様上、30日未満になると赤くなる
- 30日未満になると更新処理が走るのかもしれないが、短すぎてうまく働かない可能性を危惧
-
--x509-min-dur--x509-default-dur--x509-max-durの設定
- チャレンジ方式の追加と設定
--challenge=device-attest-01- アテステーションフォーマットにApple形式を追加
- --attestation-format=apple
- Apple Enterprise Attestation Root CAのダウンロードと指定
- 置き場所は
$STEPPATH/certsでええんでないかな --attestation-roots=$STEPPATH/certs/Apple_Enterprise_Attestation_Root_CA.pem
- 置き場所は
- step-ca独自のエクステンションを無効化した方がいいのかもしれない
- iOS上で解釈・表示ができていない
--disable-smallstep-extensions
{
"type": "ACME",
"name": "acme",
"forceCN": true,
"challenges": [
"device-attest-01"
],
"attestationFormats": [
"apple"
],
"attestationRoots": "LS0tLS1CRUdJ(中略)RS0tLS0tCg==",
"claims": {
"minTLSCertDuration": "24h0m0s",
"maxTLSCertDuration": "43800h0m0s",
"defaultTLSCertDuration": "8760h0m0s",
"enableSSHCA": true,
"disableRenewal": false,
"allowRenewalAfterExpiry": false,
"disableSmallstepExtensions": true
},
"options": {
"x509": {},
"ssh": {}
}
}
ACME構成プロファイル
- iOS側には、ACME構成プロファイルの前にルート証明書の信頼設定を
- ACME構成プロファイルはApple Configurator 2では作れない
- 手書き、MDM、3rd Partyアプリの方法でがんばれ
-
DirectoryURLは今回の場合https://[ホスト名.local]:9000/acme/acme/directory- acmeが二つ重なっているうちの片方はprovisioner名
-
ClientIdentifierは、今回の方式の場合はシリアルかUDIDで -
KeySizeはいったん256とした -
KeyTypeはECSECPrimeRandomとした -
Subjectは、今回の方式の場合はCNがシリアルかUDIDっぽかったので/CN=[シリアル] -
SubjectAltNameを入れてみたものの、うまく反映されなかったのだが深追いする気力なし
なお、こんな感じに構成プロファイル内でデバイスごとに値を書き換えないといけないので、単一のプロファイル流用はできず、デバイス数分構成プロファイルを作って準備するか、プロファイル内でシリアルを変数として当て嵌めることができるMDMでなければ耐えられない。つらい。
もしくは、MDM登録チャレンジペイロードであればシリアルやUDIDをPOSTしているので、それを元にACMEプロファイルを生成・ダウンロードさせるWebサイトを作るか。めんどうくさい。
インストールの流れ
MDMやAC2からではなく、手動でのプロファイルインストールを行った場合
構成プロファイル自体には秘密鍵や証明書は含まれていない。マスク部はホスト名。

プロファイルインストール時にACMEにより証明書を受け取る。マスク部はデバイスシリアル。
プロファイル手動インストールでは発行失敗の場合、プロファイルインストール失敗となるがMDM経由の場合はリトライとかしてくれるのだろうか。

プロファイルインストール完了後、証明書を確認することができる。
インストール時に証明書が発行されるため、(図では少しずれているが)有効になる日付が直近となる。
プロファイルを上書きインストールすれば更新される。自動更新は試していない。