
在 Fleet 中按 macOS 大版本分别强制更新使用自定义 DDM 声明 标签作用域【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet本文介绍如何在 Fleet 中突破内置 OS 更新强制仅支持全舰队单一最低补丁版本的限制通过将 Apple 的softwareupdate.enforcement.specificDDMDeclarative Device Management声明作用域到动态标签为同一舰队上不同 macOS 大版本如 macOS 15 与 macOS 26分别设定各自的补丁底线与强制期限。读完本文你将掌握从创建标签、编写 DDM 声明 JSON到通过 Fleet UI 或 GitOps 上传并验证的完整落地流程并能理解 Fleet 在服务端对这类声明所做的安全校验与冲突防护。为什么需要按大版本的更新强制Fleet 内置的 macOS 最低 OS 版本强制位于Controls OS updates允许你为整个舰队设置一个统一的最低补丁版本。当所有设备都停留在同一个 macOS 大版本时这种方式简单有效但当你正处于版本过渡期——例如同一舰队同时运行 macOS 15 和 macOS 26 的设备且两者需要不同的补丁底线macOS 15 至少 15.7.7macOS 26 至少 26.5.1——内置方案就力不从心了因为它只能表达一个全局值。本文给出的解法是绕过内置强制改用 Apple DDM声明式设备管理的自定义声明并结合 Fleet 的标签label作用域能力把每个大版本对应一份声明、每份声明只投递给匹配该大版本的设备。工作原理整体思路分两步为每个需要支持的 macOS 大版本创建一份 DDM 声明com.apple.configuration.softwareupdate.enforcement.specific在声明中指定该大版本的最低补丁版本和强制截止时间。用 osquery 动态标签识别运行某个大版本但补丁版本不足的设备把对应的声明只作用域到该标签。这样Fleet 在交付声明时会按标签匹配设备不同大版本的设备各自收到符合自己版本的强制策略互不干扰。前置条件Fleet v4.86 及更早版本需要在 Fleet 服务器上启用mdm.allow_all_declarations特性开关。通过环境变量FLEET_MDM_ALLOW_ALL_DECLARATIONS1设置并重启 Fleet 服务器。Fleet v4.87 及更高版本该开关默认开启无需额外操作。受管设备需运行macOS 14 或更高版本Apple 要求此版本及以上才支持softwareupdate.enforcement.specific声明。Fleet Premium标签作用域的自定义配置文件为付费能力。警告不要与内置强制混用。内置的 macOS 最低版本强制和本文方案都会向设备下发softwareupdate.enforcement.specific声明。两者同时启用会在设备上产生冲突声明。如果按本文操作请先在Controls OS updates中清除 macOS 的最低 OS 版本设置。这个冲突防护在 Fleet 源码中是显式实现的上传声明时会调用 handleDeclarationSoftwareUpdate它先校验rawDecl.Type是否为软件更新声明类型然后检查当前租户team是否已通过设置配置了 OS 更新——若已配置直接返回OSUpdatesAlreadyConfiguredErrorMessage的 400 错误从服务端源头杜绝双写冲突。Step 1为每个 macOS 大版本创建动态标签在 Fleet 中进入Labels为每个需要支持的大版本创建一个动态标签其匹配条件用 osquery 查询表达设备的大版本匹配目标但补丁版本尚未达到底线。macOS 15 设备目标版本 15.7.7标签名称macOS 15 update查询SELECT 1 FROM os_version WHERE major 15 AND ( minor 7 OR (minor 7 AND patch 7) );macOS 26 设备目标版本 26.5.1标签名称macOS 26 update查询SELECT 1 FROM os_version WHERE major 26 AND ( minor 5 OR (minor 5 AND patch 1) );简化写法如果声明里只写了主版本和次版本号不带补丁号查询可以相应简化。例如目标为 26.5 时SELECT 1 FROM os_version WHERE major 26 AND minor 5;其他需要覆盖的大版本依此类推。注意查询逻辑的核心是尚未达标的设备才命中标签——这正是让声明只投递给需要升级的设备的关键。注意向已达标设备投递声明的后果。如果你部署的声明目标版本低于设备当前版本声明会在设备端应用失败Fleet 端会把该配置标记为 Failed错误信息形如Error.ConfigurationCannotBeApplied: Configuration cannot be applied map[Error:[kSUCoreErrorDDMInvalidDeclarationFailure] Invalid declaration: target OS version (15.7) is older than current version (15.7.7)]这条错误实际意味着设备已经合规、无需更新但配置状态会显示为失败。所以动态标签的查询条件务必只命中未达标设备。Step 2为每个 macOS 大版本创建 DDM 声明为每个大版本单独创建一个 JSON 文件。每个文件定义要强制的最低补丁版本以及设备必须在此前完成升级的截止时间。需要按需修改两个字段TargetOSVersion要强制的最低补丁版本TargetLocalDateTime给用户足够通知时间的本地截止时间超过该时间后 macOS 会强制更新。macos-15-update-enforcement.json{ Type: com.apple.configuration.softwareupdate.enforcement.specific, Identifier: fleet.softwareupdate.macos15, Payload: { TargetOSVersion: 15.7.7, TargetLocalDateTime: 2026-07-31T23:59:59 } }macos-26-update-enforcement.json{ Type: com.apple.configuration.softwareupdate.enforcement.specific, Identifier: fleet.softwareupdate.macos26, Payload: { TargetOSVersion: 26.5.1, TargetLocalDateTime: 2026-07-31T23:59:59 } }其中TargetOSVersion是要强制的最低补丁版本TargetLocalDateTime是设备本地时间下的截止时刻两者都是强制生效所必需的字段。Identifier建议使用可辨识、全局唯一的命名如fleet.softwareupdate.macos15因为 DDM 声明按Type Identifier标识改名会被 Fleet 视为新增声明。服务端对声明类型的校验逻辑在上传过程中Fleet 会先解析 JSON 得到原始声明结构再执行 ValidateUserProvided 做安全校验仅当mdm.allow_all_declarations未启用时执行。从源码可以看到以下规则只允许com.apple.configuration.配置声明和com.apple.management.管理声明前缀的类型禁止com.apple.configuration.management.status-subscriptions状态订阅请改用查询与策略禁止com.apple.configuration.package软件包管理请走 Fleet 的 Software 标签页Identifier长度有上限约束MDMAppleDeclarationIdentifierMaxLen。由此可见softwareupdate.enforcement.specific属于允许范围内的配置声明类型而启用mdm.allow_all_declarations只是跳过上述默认校验、放行更广泛的自定义声明类型标签作用域本身并不依赖该开关。Step 3上传声明并作用域到标签方式一Fleet UI进入Controls OS settings。点击Add profile。上传macos-15-update-enforcement.json。将Display name设置为便于识别的名称例如macOS 15 update enforcement。在Target下选择Include any并勾选macOS 15 update标签。点击Save。对macos-26-update-enforcement.json重复以上步骤目标标签选择macOS 26 update。方式二GitOpsfleetctl gitops在 Fleet 的 YAML 配置中把声明挂到controls.macos_settings.custom_settings下并通过labels_include_any指定标签controls: macos_settings: custom_settings: - path: ./declarations/macos-15-update-enforcement.json labels_include_any: - macOS 15 update - path: ./declarations/macos-26-update-enforcement.json labels_include_any: - macOS 26 update然后运行fleetctl gitops应用配置。标签作用域的源码依据在服务端 上传声明的实现 中可以看到只要声明携带labels_include_any/labels_exclude_any就会先校验Premium 许可fleet.NewLicenseErrorWithCause非 Premium 会直接报错——这印证了前置条件中的许可要求同一标签不能同时出现在 include 与 exclude 列表中否则返回参数错误标签集合经validateDeclarationLabelSets校验后写入声明的LabelsIncludeAny/LabelsIncludeAll/LabelsExcludeAny字段供后续下发匹配。UI 中的Include any即对应LabelsIncludeAny语义——只要设备命中其中任意一个标签即可收到该声明。验证交付结果声明下发后逐台确认设备收到的是正确的那份声明进入Hosts按macOS 15 update标签筛选设备。点击某台主机进入OS settings标签页。确认macOS 15 update enforcement状态显示为Verified。对macOS 26 update标签重复同样的检查。边界情况与注意事项不匹配任何标签的设备不会收到更新声明。如果你还有停留在更旧大版本、希望强制迁出的设备请为它们再创建一份声明或使用 Fleet 内置强制来覆盖。勿与内置 OS 更新强制同时使用如前述两者都会下发softwareupdate.enforcement.specific服务端在 handleDeclarationSoftwareUpdate 中会拒绝在已配置 OS 更新的租户上再上传此类声明反过来如果先用声明再配置内置强制同样会造成设备端冲突。声明状态为 Failed 不一定是故障当目标版本不高于设备当前版本时设备会返回Error.ConfigurationCannotBeApplied这表示设备已合规只是 Fleet 无法将其标记为成功。版本覆盖完整如果舰队里同时存在 macOS 15、macOS 26 及更旧版本请为每个实际存在的大版本都准备好声明避免旧版本设备无人接管。小结借助 Fleet 对自定义 Apple DDM 声明的支持与标签作用域机制你可以把按 macOS 大版本分别设置补丁底线这一运维需求变成一套可复制、可 GitOps 化的流程动态标签负责识别未达标设备softwareupdate.enforcement.specific声明负责定义目标和截止时间Fleet 服务端在 apple_mdm.go 中完成类型校验、许可校验与 OS 更新冲突防护。整套方案同样适用于其他需要同舰队、多版本、差异化策略的场景是官方内置 OS 更新强制的有力补充。相关资源Fleet 服务器配置含mdm.allow_all_declarations定义Apple DDM 声明上传与校验实现软件更新声明冲突校验声明类型白名单校验相关测试用例【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考