拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Fleet MicroMDM Touchless 迁移工具:零交互将设备、SCEP/APNs 证书从 MicroMDM 导入 Fleet

后端前端企业应用运维网络安全【免费下载链接】fleetOpen device management项目地址https://gitcode.com/GitHub_Trending/fl/fleet点击查看免费下载本文以 Fleet 仓库中的 tools/mdm/migration/micromdm/touchless/README.md 及其配套 Go 脚本为主线系统讲解如何通过一条命令把 MicroMDM 数据库中已有的设备记录、APNs 推送信息、SCEP 身份证书与 ADE自动设备注册相关数据以 SQL 语句的形式迁移到 Fleet 的 MDM 数据表并导出可复用的 SCEP 证书与私钥。读完本文你将掌握该工具的参数含义、输出产物结构、底层实现原理Bolt 读取、plist 序列化、幂等 SQL 生成以及迁移后设备在 Fleet 中的表现可直接用于实际的 MicroMDM → Fleet 无接触迁移。一、为什么需要无接触touchless迁移Fleet 在迁移 MicroMDM 存量设备时提供两种路径端到端用户流程End User Workflow需要用户配合完成注销与重新注册通常借助 tools/mdm/migration/micromdm/main.go 这类 webhook 回调服务器向设备下发RemoveProfile命令完成退管再引导用户重新注册到 Fleet。无接触迁移Touchless Migration不打扰最终用户直接在服务端把 MicroMDM 数据库里的设备身份与凭据搬到 Fleet。本文的主角tools/mdm/migration/micromdm/touchless/main.go就属于这一类。无接触的价值在于设备无需人工操作Fleet 侧拿到迁移后的记录后可以直接使用原有的 APNs 推送通道向设备下发命令设备仍以原有 SCEP 身份证书完成认证从而平滑接管管理权。二、工具职责与产出物该脚本是一个 Go 程序从 MicroMDM 的 Bolt 数据库中读取信息输出两类结果证书类文件SCEP、APNs通过证书恢复以及 ADE 相关的凭据文件scep.cert/scep.key内含 SCEP CA 证书与私钥可用于恢复 ADE 所需的信任链。数据迁移文件一个包含 MySQL 语句的文件dump.sql用于将设备与注册记录导入 Fleet 数据库。从源码看main.go程序接受一个核心命令行参数--db string path to micromdm DB默认 /var/db/micromdm/micromdm.db唯一的外部依赖是安装了兼容版本的 Go以及一个可访问的 MicroMDM 数据库文件。三、运行方式与日志解读按 README 给出的示例一条典型的成功运行命令如下go run tools/mdm/migration/micromdm/touchless/main.go --db ~/projects/micromdm/micromdm.db正常执行时的输出日志2024/09/11 10:05:53 Open DB for devices 2024/09/11 10:05:53 Found 1 devices 2024/09/11 10:05:53 Wrote device/enrollment records to dump.sql 2024/09/11 10:05:53 Open DB for SCEP cert and key 2024/09/11 10:05:53 Wrote SCEP cert/key to scep.cert/scep.key日志顺序与源码中的两个匿名函数一一对应先处理设备与注册记录再处理 SCEP 证书与私钥。运行后当前目录下会生成三个文件文件内容权限dump.sql设备/注册记录的 MySQL INSERT 语句0600scep.certSCEP CA 证书PEM0600scep.keySCEP CA 私钥PKCS#1 RSAPEM0600需要特别提醒scep.key是 CA 私钥脚本以0600权限写入请妥善保管仅应在迁移场景下于受控环境中使用。四、源码剖析一设备与推送信息的读取脚本先用github.com/boltdb/bolt打开 MicroMDM 数据库再复用 MicroMDM 自身的库来读取设备与推送信息main.goboltDB, err : bolt.Open(*flDB, 0o600, nil) ps : inmem.NewPubSub() apnsDB, err : apnsbuiltin.NewDB(boltDB, ps) deviceDB, err : devicebuiltin.NewDB(boltDB) devices, err : deviceDB.List(context.Background(), device.ListDevicesOption{})这里的关键点apnsbuiltin.NewDB负责读取 APNs 推送信息MDM Topic、PushMagic、设备推送 Token对应 README 中提到的 APNs 证书/凭据迁移devicebuiltin.NewDB.List枚举全部设备记录如果设备数为 0会提示No devices found. Are you sure ... is a MicroMDM DB?用于快速校验传入的数据库路径是否正确。五、源码剖析二SCEP 身份证书的哈希映射MicroMDM 的 SCEP 证书以证书 CN 作为 key存储在 Bolt 的scep_certificatesbucket 中而设备记录只保存证书的 SHA-256 哈希。由于 depot 未暴露列出证书的接口脚本直接用 Bolt 遍历 bucket建立证书哈希 → 证书 key的映射避免把全部证书加载进内存约 2KB/张main.gocertHashToCertKey : make(map[string][]byte, len(devices)) err boltDB.View(func(tx *bolt.Tx) error { bucket : tx.Bucket([]byte(scep_certificates)) if bucket nil { log.Fatalf(No identity certificates found. Are you sure %s is a MicroMDM DB?, *flDB) } return bucket.ForEach(func(k, v []byte) error { hash : sha256.Sum256(v) certHashToCertKey[string(hash[:])] k return nil }) })随后对每台设备通过deviceDB.GetUDIDCertHash取出其证书哈希用哈希在映射中反查证书 DER 数据用x509.ParseCertificate解析出证书的过期时间NotAfter并编码为 PEM供 SQL 中的identity_cert字段使用main.go。六、源码剖析三为每台设备构造 plist 载荷MDM 协议中Fleet 依赖设备上报的Authenticate与TokenUpdate消息来识别设备身份与推送通道。脚本为每台设备重建这两个 plistAuthenticate包含 UDID、Topic、BuildVersion、DeviceName、Model、ModelName、OSVersion、ProductName、SerialNumber、IMEI、MEID 等字段main.goTokenUpdate包含 UDID、PushMagic、Token十六进制解码后的推送 Token、Topic 以及 UnlockTokenmain.go。这两个结构体使用github.com/micromdm/plist序列化随后作为文本写入 SQL。Token 与 UnlockToken 均通过hex.DecodeString还原为二进制再填入结构体SQL 侧再以十六进制编码存储token_hex。对 UDID 为空、推送信息缺失、Token 解码失败等异常设备脚本会打印FAILED日志并跳过保证单台设备异常不会中断整体迁移。七、SQL 生成详解四条幂等 INSERT对每台有效设备脚本依次生成四条 MySQL 语句全部写入dump.sql1.nano_devices设备主记录INSERT INTO nano_devices (id, serial_number, authenticate, authenticate_at, token_update, token_update_at, bootstrap_token_b64, bootstrap_token_at, identity_cert, updated_at) SELECT UDID, SerialNumber, Authenticate plist, CURRENT_TIMESTAMP, TokenUpdate plist, CURRENT_TIMESTAMP, NULLIF(bootstrap_token_b64, ), CURRENT_TIMESTAMP, NULLIF(identity_cert PEM, ), referenceTime WHERE NOT EXISTS ( SELECT 1 FROM nano_devices WHERE id UDID AND updated_at ! referenceTime ) ON DUPLICATE KEY UPDATE updated_at updated_at, -- preserve updated_at serial_number VALUES(serial_number), authenticate VALUES(authenticate), authenticate_at CURRENT_TIMESTAMP, token_update VALUES(token_update), token_update_at CURRENT_TIMESTAMP, bootstrap_token_b64 VALUES(bootstrap_token_b64), bootstrap_token_at CURRENT_TIMESTAMP, identity_cert VALUES(identity_cert);要点bootstrap_token_b64与identity_cert使用NULLIF(x, )空值会被安全地转为NULL若设备未携带 Bootstrap Token日志会提示Device with empty bootstrap token: UDIDnano_devices表要求identity_cert以-----BEGIN CERTIFICATE-----开头表级 CHECK 约束脚本输出的正是 PEM 编码证书。2.nano_enrollments注册记录INSERT INTO nano_enrollments ( id, device_id, user_id, type, topic, push_magic, token_hex, enabled, enrolled_from_migration, token_update_tally, updated_at) SELECT UDID, UDID, NULL, Device, Topic, PushMagic, token_hex, enrolled, 1, 1, referenceTime WHERE NOT EXISTS ( SELECT 1 FROM nano_enrollments WHERE id UDID AND updated_at ! referenceTime ) ON DUPLICATE KEY UPDATE updated_at updated_at, -- preserve updated_at device_id VALUES(device_id), user_id VALUES(user_id), type VALUES(type), topic VALUES(topic), push_magic VALUES(push_magic), token_hex VALUES(token_hex), enabled VALUES(enabled), token_update_tally nano_enrollments.token_update_tally 1;关键点注册类型固定为Device设备级注册user_id为NULLenrolled_from_migration置为1这是 Fleet 在 20240702123921_AddEnrolledFromMigrationColumn.go 中为nano_enrollments增加的标记列用于标识该注册来自迁移流程token_update_tally初始为 1重复导入时会递增。3.nano_seen_times播种最近可见时间INSERT INTO nano_seen_times (id, seen_time) SELECT UDID, CURRENT_TIMESTAMP WHERE NOT EXISTS ( SELECT 1 FROM nano_enrollments WHERE id UDID AND updated_at ! referenceTime ) ON DUPLICATE KEY UPDATE seen_time CURRENT_TIMESTAMP;该语句的作用正如源码注释所述为刚迁移的设备播种seen_time避免设备在首次 check-in 之前被误判为从未在线同时沿用与注册语句相同的守护条件保证迁移后又被触碰过的设备不被改写。4.nano_cert_auth_associations证书认证关联INSERT INTO nano_cert_auth_associations (id, sha256, cert_not_valid_after, updated_at) SELECT UDID, cert SHA-256 hex, NULLIF(certExpiration, ), referenceTime WHERE NOT EXISTS ( SELECT 1 FROM nano_cert_auth_associations WHERE id UDID AND updated_at ! referenceTime ) ON DUPLICATE KEY UPDATE id VALUES(id), updated_at updated_at, -- preserve updated_at sha256 VALUES(sha256), cert_not_valid_after VALUES(cert_not_valid_after);该表建立了设备 UDID ↔ SCEP 证书 SHA-256 指纹的关联Fleet 后续即可据此完成基于证书的 mTLS 设备认证。八、幂等机制referenceTime 金丝雀脚本定义了常量main.goconst referenceTime 2000-01-01 00:00:00其设计意图是迁移脚本以2000-01-01 00:00:00作为金丝雀时间戳写入updated_at。只要某条记录仍是这个时间戳脚本或任何以同样机制运行的工具就可以更新它一旦时间戳发生变化说明设备在迁移后已被 Fleet 实际处理过、发生过真实的 check-in记录将被完全忽略。这一机制让dump.sql可以安全地重复执行而不产生副作用是迁移脚本幂等性的核心。九、SCEP CA 证书与私钥的导出脚本的第二阶段用github.com/fleetdm/fleet/v4/server/mdm/scep/depot/bolt重新打开数据库通过CreateOrLoadKey与CreateOrLoadCA恢复 SCEP 的 RSA 私钥与 CA 证书main.gokey, err : scepBoltDepot.CreateOrLoadKey(2048) crt, err : scepBoltDepot.CreateOrLoadCA(key, 5, MicroMDM, US) privateKeyBytes : x509.MarshalPKCS1PrivateKey(key) privateKeyPEM : pem.EncodeToMemory(pem.Block{Type: RSA PRIVATE KEY, Bytes: privateKeyBytes}) os.WriteFile(scep.key, privateKeyPEM, 0o600) certPEM : pem.EncodeToMemory(pem.Block{Type: CERTIFICATE, Bytes: crt.Raw}) os.WriteFile(scep.cert, certPEM, 0o600)CreateOrLoadKey(2048)生成/加载 2048 位 RSA 密钥CreateOrLoadCA以 5 年有效期、CN 为MicroMDM、国家为US签发 CA 证书。这两个文件在迁移完成后可被 Fleet 用于继续签发 SCEP 证书保持与存量设备身份证书的信任链一致。十、目标表结构Fleet 的 nano_ 前缀 MDM 表dump.sql面向的表来自 Fleet 迁移脚本 20220915165115_AppleMDMTables_nanomdm.sql。该文件把开源 nanomdm 的 schema 原样引入并将表名统一加上nano_前缀以避免与 Fleet 自身表冲突涉及的完整表集合包括nano_devices设备主表id即 UDID 为主键含serial_number、identity_cert、authenticate、token_update、bootstrap_token_b64等字段及多项 CHECK 约束nano_users用户记录user_short_name、user_long_name、用户级 TokenUpdate 等nano_enrollments注册表topic、push_magic、token_hex、enabled、token_update_tallydevice_id外键指向nano_devices.idnano_commands/nano_command_results/nano_enrollment_queue命令下发与结果回传nano_push_certsAPNs 推送证书topic为主键cert_pem/key_pem/stale_tokennano_cert_auth_associations设备与 SCEP 证书指纹的认证关联表。迁移脚本生成的nano_devices、nano_enrollments、nano_seen_times、nano_cert_auth_associations四条语句正好覆盖了设备在线状态、注册通道与证书认证三条核心链路。十一、迁移后的设备行为与注意事项立即获得推送能力由于nano_enrollments中写入了topic、push_magic、token_hexFleet 可以立刻通过 APNs 向设备推送命令无需设备重新注册。设备身份保持identity_cert与nano_cert_auth_associations让存量设备仍能以原有 SCEP 证书完成 mTLS 认证。迁移标记enrolled_from_migration 1使 Fleet 可以在 UI/API 层面区分迁移设备与常规注册设备相关列定义见 AddEnrolledFromMigrationColumn.go。数据安全dump.sql、scep.cert、scep.key均以0600权限落盘私钥文件务必纳入密管流程避免泄露导致证书信任链被冒用。可重复执行referenceTime 金丝雀机制保证重复导入不会覆盖迁移后产生的新数据但仍建议在正式导入前于预发/测试数据库上先行验证dump.sql。异常跳过策略UDID 为空、推送信息缺失、证书解析失败等异常设备会被跳过并记录日志迁移完成后应核对日志中的FAILED与Skipping device条目确认遗漏范围。十二、相关配套资源迁移工具本体tools/mdm/migration/micromdm/touchless/main.go端到端用户流程的 webhook 服务tools/mdm/migration/micromdm/main.goREADME 见 tools/mdm/migration/micromdm/README.md目标表结构定义20220915165115_AppleMDMTables_nanomdm.sql迁移标记列20240702123921_AddEnrolledFromMigrationColumn.goSCEP Bolt depot 实现server/mdm/scep/depot/bolt综上MicroMDM Touchless 迁移工具以极低的运维成本完成了存量设备数据层的搬迁设备无需人工干预Fleet 即刻获得 APNs 推送通道、证书认证关联与设备基础信息为后续从 MicroMDM 平滑切换到 Fleet 提供了可靠的技术底座。赞分享后端前端企业应用运维网络安全【免费下载链接】fleetOpen device management项目地址https://gitcode.com/GitHub_Trending/fl/fleet点击查看免费下载相关推荐Fleet 集成 MicroMDM 迁移工具用 RemoveProfile Webhook 与 touchless 脚本完成 MDM 平滑迁移Fleet 集成 MicroMDM 迁移工具用 RemoveProfile Webhook 与 touchless 脚本完成 MDM 平滑迁移 本指南以 Fl后端前端企业应用运维网络安全智能分辨率同步方案彻底解决跨设备显示适配难题智能分辨率同步方案彻底解决跨设备显示适配难题 ResolutionAutomation是一款专为Moonlight串流设计的智能分辨率匹配工具通过自动化调整后端前端企业应用运维网络安全终极指南3步掌握Pencil Project EPZ文件格式的完整解析终极指南3步掌握Pencil Project EPZ文件格式的完整解析 Pencil Project是一款优秀的开源UI原型设计工具其独特的EPZ文件格式是后端前端企业应用运维网络安全上一篇prek的跨平台测试确保在所有系统上的兼容性下一篇【免费下载】 芋道管理后台使用与部署教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门