KMFDDM
KMFDDM是一个苹果声明式设备管理(DDM)服务器。它与NanoMDM一起工作。
实验性的
警告:KMFDDM是实验性的。在这个时候,它被认为是一个研发平台,以进一步了解和研究DDM协议和设备操作。代码是不完善的,几乎没有文档。预计API会被删除和改变。期待数据模型、数据库模式或整个管理范式发生巨大的变化。预计将不得不擦除任何配置并重新开始。期待整个项目在任何时候都不能正常运行。
要求
- 一个工作的NanoMDM v0.3.0+环境
- 对NanoMDM实例的网络访问。
- 具有声明式设备管理(DDM)功能的设备:iOS 15.0+, macOS 13.0+ (Ventura), 等等。
- MySQL 8.0.19以上数据库
- 包括Python 3和shell脚本工具(技术上是可选的,但有帮助)
开始使用&文档
在进行快速入门指南之前,请阅读此README。它将为KMFDDM的运行和一些假设奠定一些概念性的基础。
- 快速入门指南,让KMFDDM快速启动和运行。
概念和术语
声明
如果你不熟悉什么是声明(或DDM),请查看苹果公司2021年WWDC的第一个视频"认识声明式设备管理"。
声明是JSON blobs,包括Identifier,Type, 和Payload 字段。一个额外的字段,ServerToken ,唯一标识一个声明的 "版本",但KMFDDM为你处理这个字段。Identifier 是你喜欢的任何唯一值,而Payload 对象字段的内容是由声明的类型定义的(如在Type 字段中指定)。各种类型和有效载荷由苹果公司记录。这里有一个声明的例子。
{
"Type": "com.apple.management.organization-info",
"Payload": {
"Name": "ACME Widgets Co."
},
"Identifier": "c55aad00-126f-4ed4-be8a-df58d5856c97"
}
作为一个旁观者,这是用附带的ideclr.py工具生成的:
$ ./tools/ideclr.py org-info 'ACME Widgets Co.'
另外,我不建议在Identifier 字段中使用UUID(为了你自己的理智)--它只是一个默认值。ideclr.py 有-i 开关来指定你自己的。
代号
声明式设备管理有两个(半)不同的 "令牌"。其中一个是声明ServerToken 字段,它唯一地标识了一个声明的 "版本"。当声明发生变化时,这个字段表示声明在注册的设备上是否已经过时(与服务器提供的相比)。这个字段在KMFDDM中为你管理,每次你添加一个新的或更新现有的声明时都会更新。作为一个实现细节,它是声明中字段值的散列。
另一个标记(或者说是一个半标记)是DeclarationsToken ,它是声明项目和设备标记(或只是标记)的一部分。与声明类似,这个令牌可以识别注册设备的声明集合是否已经过期,以及是否需要从服务器上更新声明。这个令牌(实际上对声明项目和设备令牌来说是一样的)也是为你管理的,作为一个实现细节,它是从包含在注册的声明项目中的每个声明的ServerToken's。
声明项目和设备令牌
根据DDM协议,声明项目(以及密切相关的设备令牌或只是令牌)是特定注册的声明Identifier's 和声明ServerToken's 的集合。根据上述规定,他们也包括他们自己单独的服务器令牌值。在KMFDDM中,声明项目(和设备令牌)是由所有注册的分配集(以及声明)"合成 "的。更多信息见下文。
集合
在KMFDDM中,一个 "集 "是一个命名的声明集合。声明与集合有多对多的关系:也就是说,一个声明可以 "在 "许多不同的集合中,集合可以包含许多不同的声明。集可以被认为是声明的 "逻辑 "集合。另一种思考方式是 "命名 "声明项。集合本身是 "独立的",并不自动与注册或注册ID相关。
报名
套餐可以与NanoDM的注册ID以多对多的关系联系起来:即注册ID可以与许多套装联系起来,套装也可以与许多注册ID联系起来。值得注意的是,声明不能直接与注册ID相关联。声明只能与集合相关联。
合并
由于上述集合和招生的关联,KMFDDM动态地 "合成 "声明集合为一个招生ID的单一声明项目。通过这种方式,我们可以支持灵活地配置声明到招生的映射关系。比如说:
- 旨在为所有入学的声明(包含在集合中)。
- 宣告(包含在集合中),旨在为入学的群体,如。
- 业务单位、部门、团队等。
- 逻辑或功能分组。例如,用于特定的配置或设置。
- 只针对单个注册者的声明(包含在集合中)。
- 值得注意的是,这允许支持每个学员的管理属性。
这些关联也可以反向工作,当一个单一的声明被修改时,KMFDDM知道如何找到所有适用的注册ID,并通过DM命令通知。
在这个例子中,我们可以看到(在其他可能的组合中):
enroll_1将 "合成 "一个包括 和 的声明项目,而没有其他的。decl_1decl_2enroll_2将包括 , , 和 ,没有其他。decl_1decl_2decl_3enroll_3将包括 , , 和 ,没有其他的。decl_3decl_4decl_5
在修改的情况下。
- 如果
decl_1,decl_2, 或set_1被修改,那么enroll_1和enroll_2将被通知。 - 如果
decl_3被修改,那么enroll_2和enroll_3将被通知。 - 如果
set_2被修改,那么enroll_2将被通知。 - 如果
set_3被修改,那么enroll_3将被通知。 - 如果
decl_4,decl_5,set_3, 或set_4被修改,那么只有enroll_3将被通知。
你将不得不维护哪些集被分配给哪些个人注册ID(当然,哪些个人申报被分配给哪些集)。但是,一旦你这样做了,KMFDDM就会处理剩下的事情。
特点
- 代币管理:
- 申报、申报项目和设备令牌中的版本/更改 "令牌 "都为你管理。
- 代币是为你创建、更新和生成的。你只需更新你的 "任务 "和你的声明,其余的由KMFDDM来处理。
- 自动通知:
- 当关联或声明内容发生变化时,设备会被自动通知(即发送
DeclarationManagementMDM命令)。 - 这包括过渡性地通知那些依赖关系发生变化的设备。
- 对于单一的注册通知,我们在
DeclarativeManagement命令中直接包括设备令牌。
- 当关联或声明内容发生变化时,设备会被自动通知(即发送
- 声明引用跟踪:
- 我们防止声明引用不存在的声明,保持所有声明的一致性(参考完整性)。
- 然而,这并没有延伸到集合关联;这取决于你如何保持有效。
- 状态通道数据 "缓存":
- 我们存储注册的声明状态和错误,以便以后检索和解构。
- 我们将所有非声明、非错误的数据存储为 "值",以便以后检索和解压缩。这对于检查一个报名者支持哪些声明或状态订阅是很有用的。
- 受限制的声明检索:
- 通过表连接的方式,我们只检索与注册ID相关的声明(过渡性的)。也就是说,注册者不能访问不是为他们准备的声明。这有点像一个ACL。算是吧。
- 这本身不是一个设计目标,只是一个快乐的意外。
警告和注意事项
- 报名ID集关联是 "永远的":
- 一旦你给一个集合分配了一个注册ID,它就永远被分配了,直到你取消分配它。
- 如果一个设备被取消注册或以其他方式在NanoMDM中变得无人管理,它仍然会收到来自KMFDDM的通知(排队的MDM命令)。
- 你从KMFDDM "取消注册 "一个设备,通过API将注册ID与任何集合分离。请记住,这不会关闭DDM的注册 - 这只是停止未来的通知。
- 这也将通知设备,它不再有任何声明需要管理。这与DDM的 "取消注册 "一样好。
- 你可以琐碎地创建无效的申报集:
- 对于从集合内的其他声明中引用声明,没有做太多的审查。也就是说,你可以将一个声明添加到一个集合中,而这个集合中引用的是另一个不在该集合中的声明。如果另一个集合不包含这个缺失的声明,这将最终成为一个由入学报告的错误。
- 然而,大多数声明模型问题会在DDM状态报告通道上反馈给你。每个招生单位主动管理的申报项目状态被保存下来,可以被检索和检查。
- 但还是要注意:注意什么被分配到了哪里。
- 外壳脚本可能很混乱:
- 大多数shell脚本工具都需要位置参数,而哪个位置参数是什么并不总是很明显。特别是对于 "关联 "脚本来说。
- 一般来说,第一个参数是在文件名的第一个实体之后。例如,
api-set-declarations-put.sh是关于集合和声明之间的关联,第一个参数是集合名称,第二个是声明标识符。
- 过度通知:
- 由于在SQL中使用了
ON DUPLICATE KEY,我们并不能总是准确地判断出哪些报名者不需要被通知。因此,当声明或集合发生变化时,我们可能会过度通知一些(或很多)成员。 - 然而,这在技术上并不是一个问题,因为DDM协议的 "令牌 "架构不会考虑声明的实际变化。只是需要注意的是,这可能会浪费MDM命令和DDM令牌及往返次数。
- 由于在SQL中使用了