diff --git a/changes/18849-config-profiles-exclude-labels b/changes/18849-config-profiles-exclude-labels index 62e29a1efe..4c1d41ecfb 100644 --- a/changes/18849-config-profiles-exclude-labels +++ b/changes/18849-config-profiles-exclude-labels @@ -2,3 +2,4 @@ * Added the API changes to support the `labels_include_all` and `labels_exclude_any` fields (and accept the deprecated `labels` field as an alias for `labels_include_all`). * Added `fleetctl gitops` and `fleetctl apply` support for `labels_include_all` and `labels_exclude_any` to configure a custom setting. * Updated the profile reconciliation logic to handle the new "exclude any" labels. +* Fix bug where macOS declarations were stuck in "to be removed" state indefinitely. diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go index 17f6996ba7..bdeb1a99f4 100644 --- a/server/datastore/mysql/apple_mdm.go +++ b/server/datastore/mysql/apple_mdm.go @@ -4015,10 +4015,18 @@ FROM host_mdm_apple_declarations hmad JOIN mdm_apple_declarations mad ON hmad.declaration_uuid = mad.declaration_uuid WHERE - hmad.host_uuid = ?` + hmad.host_uuid = ? AND hmad.operation_type = ?` + + // NOTE: the token generated as part of this query decides if the DDM session + // proceeds with sending the declarations - if the token differs from what + // the host last applied, it will proceed. That's why we use only the "to be + // installed" declarations for the token generation. If some declarations get + // removed, then they will be ignored in the token generation, which will + // change the token and make the DDM session proceed (and declarations not + // sent get removed). var res fleet.MDMAppleDDMDeclarationsToken - if err := sqlx.GetContext(ctx, ds.reader(ctx), &res, stmt, hostUUID); err != nil { + if err := sqlx.GetContext(ctx, ds.reader(ctx), &res, stmt, hostUUID, fleet.MDMOperationTypeInstall); err != nil { return nil, ctxerr.Wrap(ctx, err, "get DDM declarations token") }