前言
關于MDM,谷歌搜遍了也搜不出多少資料,甚至有的資料會誤導小伙伴們。我實現了MDM并且整理了一份詳細的文檔,供大家參考,表述有誤之處請見諒并及時在評論里告知我修改。
轉載請注明出處:http://www.lxweimin.com/p/2173e0df5761
參考鏈接:
http://www.lxweimin.com/p/fef831dfe12c
http://blog.csdn.net/column/details/ios-mdm.html
http://blog.csdn.net/kmyhy/article/details/23171017
http://www.mbaike.net/mdm/24.html
參考文檔:(鏈接我就不放了,大家自己找吧,找不到也沒關系)
InsideAppleMDM.pdf
CommandReference.pdf
正文
以下“服務器”都是指MDM服務器,而且必須是https服務器
MDM服務器與APNS、設備的大致通信流程
1、生成并配置好mobileconfig文件,放在服務器上
2、設備訪問服務器上的mobileconfig文件,點擊注冊以及信任按鈕后,設備主動發起請求mobileconfig里的checkin URL。設備首先發起Authenticate,服務端錄入數據后返回空plist,接著設備發起TokenUpdate,服務端錄入數據后返回空plist。
3、以鎖屏為例,服務端將鎖屏命令發給APNS,當蘋果的 APNS 服務器通知設備訪問 MDM 服務器時,設備首先會向服務器(mobileconfig里的server URL)發送一個Status:Idle 消息(如果設備空閑),表示 MDM 服務器現在可以把指令取給它執行。服務器組裝成 Plist 文件響應給它。
4、設備執行完命令,會再次向 server 發送 Acknowledged 消息,告訴服務器執行狀態,然后服務器簡單回復一個空響應(即200),并關閉連接。
以下是MDM vendor和customer申請制作
MDM Vendor申請(必須是企業版開發者賬號)
1、前往https://developer.apple.com/contact/submit.php給蘋果留言,說明你要申請MDM以及申請理由。
2、若干天后,蘋果會回復一封郵件,讓你打電話給他們,并且給你提供了一個case number。打電話時必須要報開發者證書代理人姓名,以及case number,才會給你開放。
3、客服會幫你開通,成功后她會發給你一封郵件,帶有MDM的詳細介紹鏈接,然后在developer center里,創建生產證書那邊會新增一個MDM CSR選項,表示申請成功。
MDM 證書制作和申請
(建議在Mac電腦下操作,如果是Windows則要先安裝openssl和python,(Mac自帶了它們),而且命令可能有區別,建議所有文件都統一放到一個文件夾下!所有命令都在該文件夾下操作!以下步驟需要輸入密碼,請務必記住密碼,建議統一所有密碼!)
創建MDM Vendor CSR,并上傳到developer center創建MDM證書
1、鑰匙串->鑰匙串訪問->證書助理->從證書頒發機構請求證書->填寫開發者賬號的Apple ID(例如:myCompany@qq.com)、常用名稱(公司名稱+MDM,例如:MyCompany MDM)、選擇存儲到磁盤,生成CertificateSigningRequest.certSigningRequest,保存.
2、前往developer center,創建證書->MDM CSR,上傳剛才創建的CertificateSigningRequest.certSigningRequest,生成mdm.cer,下載下來,雙擊安裝到鑰匙串(登錄->證書)。
創建MDM推送CSR
再次打開鑰匙串->鑰匙串訪問->證書助理->從證書頒發機構請求證書->填寫開發者賬號的Apple ID(例如:myCompany@qq.com)、常用名稱(公司名稱+MDMPush,例如:MyCompany MDMPush)、選擇存儲到磁盤,生成mdm_push.certSigningRequest,保存.
導出私鑰并制作證書
1、點擊展開mdm.cer安裝到鑰匙串的證書,導出私鑰為private.p12,保存。
2、將私鑰private.p12提取出私鑰
openssl pkcs12 -in private.p12 -nocerts -out key.pem
3、提取證書
openssl pkcs12 -in private.p12 -clcerts -nokeys -out cert.pem
4、將證書轉換成DES格式
openssl x509 -in cert.pem -inform PEM -out mdm.cer -outform DES
5、去掉private key密碼
openssl rsa -in key.pem -out private.key
使用mdm_vendor_sign工具制作CSR
1、下載mdm_vendor_sign(https://github.com/grinich/mdmvendorsign)
2、運行python mdm_vendor_sign.py --key private.key --csr mdm_push.certSigningRequest --mdm mdm.cer --out applepush.csr
3、運行成功后,會提示 Go upload file 'applepush.csr' to identity.apple.com/pushcert !,否則為不成功。
4、如果不成功,則需要做一些改動:
首先手動下載AppleWWDRCA.cer證書到此目錄 ([https://developer.apple.com/certificationauthority/AppleWWDRCA.cer](https://developer.apple.com/certificationauthority/AppleWWDRCA.cer))
修改mdm_vendor_sign.py 代碼128行為:intermediate_cer = open(‘AppleWWDRCA.cer','r').read()
再次運行即可。
從Apple獲取推送證書
1、將上一步生成的applepush.csr上傳到[https://identity.apple.com/pushcert](https://identity.apple.com/pushcert)
2、下載推送證書,安裝到鑰匙串,顯示 APSP:xxxxxx
3、導出該推送證書為p12,給服務端使用。
MDM Customer
(Vendor生成后的證書是通用的,而接下來的customer則是和服務器地址有關,所以更換服務器地址時則要重新完成以下步驟)
生成配置mobileconfig文件
1、下載IPCU(iPhone Configuration Utility,網上搜一下就有下載地址,如果下載下來的發現無法完成以下步驟,說明你下錯了,再去找找)(網上說蘋果已廢棄它,實際上廢棄的僅僅只是它的主要功能而已,它仍然能夠用于配置生成mobileconfig文件)。
2、打開IPCU,選擇配置描述文件->新建,即新建一個配置描述文件
3、點擊通用,填寫名稱、標識符(該描述文件的唯一標識,例如:com.公司名.mdm)、機構、描述、安全性
4、點擊憑證-> + ,添加服務器的ca根證書,再點擊+,添加用服務器證書和key生成的p12文件,填寫密碼。(如果不清楚https服務器證書如何生成,請參考底下的“https生成自簽名證書”)
5、點擊移動設備管理,填寫服務器URL(server)、登記URL(checkin),打開鑰匙串,找到vendor步驟里安裝的推送證書(APSP:xxxxxx),雙擊,復制用戶id,粘貼到主題。 身份選擇在憑證里添加的p12,“移除時檢查”勾選上時,在移除描述文件時會向MDM服務器發起checkout請求,建議勾選,其他的選項根據需求去勾選,最后一項使用開發APNS服務器不要勾選!
6、導出->安全性選擇“無”,導出為mobileconfig文件。
7、將mobileconfig放在服務器上,提供下載接口,設備用safari訪問該接口,即可自動打開設置進入描述文件的安裝界面,點擊注冊->注冊->信任,如果安裝成功,到此步驟即完成了證書的申請配置以及描述文件的配置安裝,接下來就是MDM服務器的搭建和調試與設備的通信了。
8、設備與服務端的請求都是PUT請求,具體可通過抓包查看,服務端的代碼可參考https://github.com/zuoyy/IOS-MDM-Server
實現了功能還不夠,仍然有幾個問題需要解決:
1、客戶端如何檢查是否已安裝了描述文件?(即是否可控?):
解決方案:目前我能想到的辦法是通過判斷當前服務器的https證書是否已受信任來解決,因為描述文件攜帶的憑證含有服務器的https證書,如果判斷的結果為已信任,則說明已安裝了該描述文件,可接受控制;否則就是沒有安裝了。
判斷的代碼如下:
<pre>
<code>
+ (BOOL)IsCertificatesTrusted:(NSArray<NSData *> *)certDatas {
if (certDatas.count == 0) {
return NO;
}
CFMutableArrayRef certs = CFArrayCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeArrayCallBacks);
for (NSData *certData in certDatas) {
SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certData);
if (!cert) {
continue;
}
CFArrayAppendValue(certs, cert);
CFRelease(cert);
}
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef trust;
OSStatus err = SecTrustCreateWithCertificates(certs, policy, &trust);
CFRelease(certs);
CFRelease(policy);
if (!trust) {
return NO;
}
if (err != errSecSuccess) {
CFRelease(trust);
return NO;
}
SecTrustResultType trustResult = -1;
err = SecTrustEvaluate(trust, &trustResult);
CFRelease(trust);
if (err != errSecSuccess) {
return NO;
}
if(trustResult == kSecTrustResultUnspecified) {
return YES;
} else {
return NO;
}
}
</code>
</pre>
2、斷網情況下移除描述文件,服務器如何更新數據庫?
如果你在配置mobileconfig時有勾選上“移除時檢查”,那么在聯網情況下如果移除描述文件,設備會主動發起checkout請求告訴服務器設備已退出控制,服務器可更新數據庫。
但是斷網的情況下怎么辦?
雖然第一個問題解決了客戶端判斷設備是否已安裝了描述文件,但是設備在checkin提交的設備唯一標識是UDID,而IOS是不允許用代碼獲取設備的UDID的,也就是說,客戶端無法告訴服務器設備當前到底可不可控。
在谷歌上搜索到了這么一篇文章:http://www.mbaike.net/mdm/24.html
從中想到的方案是:
服務端可通過定期主動發起查詢命令來判斷當前設備是否可控。
該方案理論上可行,但不知是否會引發其他問題,待驗證。如果有大神有完美的解決方案,請帶我。
https生成自簽名證書
一、創建CA證書
1、創建一個私鑰,命名為rootCA.key
openssl genrsa -out rootCA.key 2048
2、創建根證書,命名為rootCA.cer,(common name填寫服務器地址)
openssl req -x509 -new -key rootCA.key -out rootCA.cer -days 730
######二、制作自簽名 SSL 證書
1、創建一個私鑰,命名為server.key
openssl genrsa -out server.key 2048
2、創建CSR
openssl req -new -out server.req -key server.key -subj /CN=127.0.0.1/CN=填寫服務器地址/CN=localhost
3、用CSR創建SSL證書
openssl x509 -req -in server.req -out server.cer -CAkey rootCA.key -CA rootCA.cer -days 36500 -CAcreateserial -CAserial server.serial
4、將 .key 和 .cer 文件導出為 .p12 證書
openssl pkcs12 -export -in server.cer -inkey server.key -out server.p12 -name "server"
5、將 .p12 文件導入到 Java keystore 中
keytool -importkeystore -v -srckeystore server.p12 -srcstoretype pkcs12 -srcstorepass 密碼 -destkeystore server.keystore -deststoretype jks -deststorepass 密碼