mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
Fail DDM profiles if response is UnknownDeclarationType (#31606)
fixes: #30835 <img width="763" height="201" alt="image" src="https://github.com/user-attachments/assets/66345ff7-46bd-4321-86a5-17031ffb2888" /> # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually
This commit is contained in:
parent
0773f2cc02
commit
20c282f1a5
5 changed files with 32 additions and 5 deletions
1
changes/30853-fail-unknown-declaration-type-ddm-errors
Normal file
1
changes/30853-fail-unknown-declaration-type-ddm-errors
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Mark DDM profiles as failed if response comes back with Unknown Declaration Type error, and improve upload validation for declaration type.
|
||||
|
|
@ -682,8 +682,8 @@ func (r *MDMAppleRawDeclaration) ValidateUserProvided() error {
|
|||
return NewInvalidArgumentError(r.Type, "Declaration profile can’t include status subscription type. To get host’s vitals, please use queries and policies.")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r.Type, "com.apple.configuration") {
|
||||
return NewInvalidArgumentError(r.Type, "Only configuration declarations (com.apple.configuration) are supported.")
|
||||
if !strings.HasPrefix(r.Type, "com.apple.configuration.") {
|
||||
return NewInvalidArgumentError(r.Type, "Only configuration declarations (com.apple.configuration.) are supported.")
|
||||
}
|
||||
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -6393,7 +6393,7 @@ func (svc *MDMAppleDDMService) handleDeclarationStatus(ctx context.Context, dm *
|
|||
switch {
|
||||
case r.Active && r.Valid == fleet.MDMAppleDeclarationValid:
|
||||
status = fleet.MDMDeliveryVerified
|
||||
case r.Valid == fleet.MDMAppleDeclarationInvalid:
|
||||
case r.Valid == fleet.MDMAppleDeclarationInvalid || isUnknownDeclarationType(r):
|
||||
status = fleet.MDMDeliveryFailed
|
||||
detail = apple_mdm.FmtDDMError(r.Reasons)
|
||||
case r.Valid == fleet.MDMAppleDeclarationValid: // should be rare/never
|
||||
|
|
@ -6441,6 +6441,14 @@ func (svc *MDMAppleDDMService) handleDeclarationStatus(ctx context.Context, dm *
|
|||
return nil
|
||||
}
|
||||
|
||||
// Checks the active, valid and first reason to verify if it is an unknown declaration type error
|
||||
func isUnknownDeclarationType(declarationResponse fleet.MDMAppleDDMStatusDeclaration) bool {
|
||||
return !declarationResponse.Active &&
|
||||
declarationResponse.Valid == fleet.MDMAppleDeclarationUnknown &&
|
||||
len(declarationResponse.Reasons) > 0 &&
|
||||
declarationResponse.Reasons[0].Code == "Error.UnknownDeclarationType"
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Generate ABM keypair endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -811,6 +811,11 @@ func TestNewMDMAppleDeclaration(t *testing.T) {
|
|||
_, err := svc.NewMDMAppleDeclaration(ctx, 0, bytes.NewReader(b), nil, "name", fleet.LabelsIncludeAll)
|
||||
assert.ErrorContains(t, err, "Fleet variable")
|
||||
|
||||
// decl type missing actual type
|
||||
b = declarationForTestWithType("D1", "com.apple.configuration")
|
||||
_, err = svc.NewMDMAppleDeclaration(ctx, 0, bytes.NewReader(b), nil, "name", fleet.LabelsIncludeAll)
|
||||
assert.ErrorContains(t, err, "Only configuration declarations (com.apple.configuration.) are supported")
|
||||
|
||||
ds.NewMDMAppleDeclarationFunc = func(ctx context.Context, d *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
return d, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMBatchUpload() {
|
|||
}}, http.StatusUnprocessableEntity)
|
||||
|
||||
errMsg := extractServerErrorText(res.Body)
|
||||
require.Contains(t, errMsg, "Only configuration declarations (com.apple.configuration) are supported")
|
||||
require.Contains(t, errMsg, "Only configuration declarations (com.apple.configuration.) are supported")
|
||||
|
||||
// "com.apple.configuration.softwareupdate.enforcement.specific" type should fail
|
||||
res = s.Do("POST", "/api/latest/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: []fleet.MDMProfileBatchPayload{
|
||||
|
|
@ -976,6 +976,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
declarations := []fleet.MDMProfileBatchPayload{
|
||||
{Name: "N1.json", Contents: declarationForTest("I1")},
|
||||
{Name: "N2.json", Contents: declarationForTest("I2")},
|
||||
{Name: "Unknown.json", Contents: declarationForTestWithType("I3", "com.apple.configuration.")},
|
||||
}
|
||||
// add global declarations
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: declarations}, http.StatusNoContent)
|
||||
|
|
@ -988,6 +989,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
assertHostDeclarations(mdmHost.UUID, []*fleet.MDMAppleHostDeclaration{
|
||||
{Identifier: "I1", Status: &fleet.MDMDeliveryPending, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I2", Status: &fleet.MDMDeliveryPending, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I3", Status: &fleet.MDMDeliveryPending, OperationType: fleet.MDMOperationTypeInstall},
|
||||
})
|
||||
|
||||
// host gets a DDM sync call
|
||||
|
|
@ -1004,13 +1006,15 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
var items fleet.MDMAppleDDMDeclarationItemsResponse
|
||||
require.NoError(t, json.Unmarshal(body, &items))
|
||||
|
||||
var i1ServerToken, i2ServerToken string
|
||||
var i1ServerToken, i2ServerToken, i3ServerToken string
|
||||
for _, d := range items.Declarations.Configurations {
|
||||
switch d.Identifier {
|
||||
case "I1":
|
||||
i1ServerToken = d.ServerToken
|
||||
case "I2":
|
||||
i2ServerToken = d.ServerToken
|
||||
case "I3":
|
||||
i3ServerToken = d.ServerToken
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1018,6 +1022,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
assertHostDeclarations(mdmHost.UUID, []*fleet.MDMAppleHostDeclaration{
|
||||
{Identifier: "I1", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I2", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I3", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
})
|
||||
|
||||
// host sends a partial DDM report
|
||||
|
|
@ -1030,6 +1035,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
assertHostDeclarations(mdmHost.UUID, []*fleet.MDMAppleHostDeclaration{
|
||||
{Identifier: "I1", Status: &fleet.MDMDeliveryVerified, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I2", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I3", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
})
|
||||
|
||||
// host sends a report with a wrong (could be old) server token for I2, nothing changes
|
||||
|
|
@ -1042,6 +1048,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
assertHostDeclarations(mdmHost.UUID, []*fleet.MDMAppleHostDeclaration{
|
||||
{Identifier: "I1", Status: &fleet.MDMDeliveryVerified, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I2", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I3", Status: &fleet.MDMDeliveryVerifying, OperationType: fleet.MDMOperationTypeInstall},
|
||||
})
|
||||
|
||||
// host sends a full report, declaration I2 is invalid
|
||||
|
|
@ -1049,12 +1056,18 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
|
|||
report.StatusItems.Management.Declarations.Configurations = []fleet.MDMAppleDDMStatusDeclaration{
|
||||
{Active: true, Valid: fleet.MDMAppleDeclarationValid, Identifier: "I1", ServerToken: i1ServerToken},
|
||||
{Active: false, Valid: fleet.MDMAppleDeclarationInvalid, Identifier: "I2", ServerToken: i2ServerToken},
|
||||
{Active: false, Valid: fleet.MDMAppleDeclarationUnknown, Identifier: "I3", ServerToken: i3ServerToken, Reasons: []fleet.MDMAppleDDMStatusErrorReason{
|
||||
{
|
||||
Code: "Error.UnknownDeclarationType",
|
||||
},
|
||||
}},
|
||||
}
|
||||
_, err = device.DeclarativeManagement("status", report)
|
||||
require.NoError(t, err)
|
||||
assertHostDeclarations(mdmHost.UUID, []*fleet.MDMAppleHostDeclaration{
|
||||
{Identifier: "I1", Status: &fleet.MDMDeliveryVerified, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I2", Status: &fleet.MDMDeliveryFailed, OperationType: fleet.MDMOperationTypeInstall},
|
||||
{Identifier: "I3", Status: &fleet.MDMDeliveryFailed, OperationType: fleet.MDMOperationTypeInstall},
|
||||
})
|
||||
|
||||
// do a batch request, this time I2 is deleted
|
||||
|
|
|
|||
Loading…
Reference in a new issue