package apple_mdm
import (
"context"
"errors"
"fmt"
"log/slog"
"net/url"
"os"
"strings"
"testing"
"time"
"github.com/fleetdm/fleet/v4/ee/server/service/digicert"
"github.com/fleetdm/fleet/v4/ee/server/service/scep"
"github.com/fleetdm/fleet/v4/server/contexts/license"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/mdm/apple/mobileconfig"
"github.com/fleetdm/fleet/v4/server/mock"
digicert_mock "github.com/fleetdm/fleet/v4/server/mock/digicert"
scep_mock "github.com/fleetdm/fleet/v4/server/mock/scep"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPreprocessProfileContents(t *testing.T) {
ctx := context.Background()
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = "https://test.example.com"
appCfg.MDM.EnabledAndConfigured = true
ds := new(mock.Store)
// No-op
svc := scep.NewSCEPConfigService(logger, nil)
digiCertService := digicert.NewService(digicert.WithLogger(logger))
err := preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, nil, nil, nil, nil, nil)
require.NoError(t, err)
hostUUID := "host-1"
cmdUUID := "cmd-1"
var targets map[string]*fleet.CmdTarget
populateTargets := func() {
targets = map[string]*fleet.CmdTarget{
"p1": {CmdUUID: cmdUUID, ProfileIdentifier: "com.add.profile", EnrollmentIDs: []string{hostUUID}},
}
}
hostProfilesToInstallMap := make(map[fleet.HostProfileUUID]*fleet.MDMAppleBulkUpsertHostProfilePayload, 1)
hostProfilesToInstallMap[fleet.HostProfileUUID{HostUUID: hostUUID, ProfileUUID: "p1"}] = &fleet.MDMAppleBulkUpsertHostProfilePayload{
ProfileUUID: "p1",
ProfileIdentifier: "com.add.profile",
HostUUID: hostUUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &fleet.MDMDeliveryPending,
CommandUUID: cmdUUID,
Scope: fleet.PayloadScopeSystem,
}
userEnrollmentsToHostUUIDsMap := make(map[string]string)
populateTargets()
profileContents := map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + fleet.FleetVarNDESSCEPProxyURL),
}
var updatedPayload *fleet.MDMAppleBulkUpsertHostProfilePayload
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
require.Len(t, payload, 1)
updatedPayload = payload[0]
for _, p := range payload {
require.NotNil(t, p.Status)
assert.Equal(t, fleet.MDMDeliveryFailed, *p.Status)
assert.Equal(t, cmdUUID, p.CommandUUID)
assert.Equal(t, hostUUID, p.HostUUID)
assert.Equal(t, fleet.MDMOperationTypeInstall, p.OperationType)
assert.Equal(t, fleet.PayloadScopeSystem, p.Scope)
}
return nil
}
// Can't use NDES SCEP proxy with free tier
ctx = license.NewContext(ctx, &fleet.LicenseInfo{Tier: fleet.TierFree})
err = preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, nil)
require.NoError(t, err)
require.NotNil(t, updatedPayload)
assert.Contains(t, updatedPayload.Detail, "Premium license")
assert.Empty(t, targets)
// Can't use NDES SCEP proxy without it being configured
ctx = license.NewContext(ctx, &fleet.LicenseInfo{Tier: fleet.TierPremium})
updatedPayload = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, &fleet.GroupedCertificateAuthorities{})
require.NoError(t, err)
require.NotNil(t, updatedPayload)
assert.Contains(t, updatedPayload.Detail, "not configured")
assert.NotNil(t, updatedPayload.VariablesUpdatedAt)
assert.Empty(t, targets)
// Unknown variable
profileContents = map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_BOZO"),
}
updatedPayload = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, nil)
require.NoError(t, err)
require.NotNil(t, updatedPayload)
assert.Contains(t, updatedPayload.Detail, "FLEET_VAR_BOZO")
assert.Empty(t, targets)
ndesPassword := "test-password"
ds.GetAllMDMConfigAssetsByNameFunc = func(ctx context.Context,
assetNames []fleet.MDMAssetName, _ sqlx.QueryerContext,
) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) {
return map[fleet.MDMAssetName]fleet.MDMConfigAsset{
fleet.MDMAssetNDESPassword: {Value: []byte(ndesPassword)},
}, nil
}
ds.BulkUpsertMDMAppleHostProfilesFunc = nil
var updatedProfile *fleet.HostMDMAppleProfile
ds.UpdateOrDeleteHostMDMAppleProfileFunc = func(ctx context.Context, profile *fleet.HostMDMAppleProfile) error {
updatedProfile = profile
require.NotNil(t, updatedProfile.Status)
assert.Equal(t, fleet.MDMDeliveryFailed, *updatedProfile.Status)
assert.Equal(t, cmdUUID, updatedProfile.CommandUUID)
assert.Equal(t, hostUUID, updatedProfile.HostUUID)
assert.Equal(t, fleet.MDMOperationTypeInstall, updatedProfile.OperationType)
return nil
}
ds.BulkUpsertMDMManagedCertificatesFunc = func(ctx context.Context, payload []*fleet.MDMManagedCertificate) error {
assert.Empty(t, payload)
return nil
}
adminUrl := "https://example.com"
username := "admin"
password := "test-password"
groupedCAs := &fleet.GroupedCertificateAuthorities{
NDESSCEP: &fleet.NDESSCEPProxyCA{
URL: "https://test-example.com",
AdminURL: adminUrl,
Username: username,
Password: password,
},
}
// Could not get NDES SCEP challenge
profileContents = map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + fleet.FleetVarNDESSCEPChallenge),
}
scepConfig := &scep_mock.SCEPConfigService{}
scepConfig.GetNDESSCEPChallengeFunc = func(ctx context.Context, proxy fleet.NDESSCEPProxyCA) (string, error) {
assert.Equal(t, ndesPassword, proxy.Password)
return "", scep.NewNDESInvalidError("NDES error")
}
updatedProfile = nil
populateTargets()
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
assert.Empty(t, payload) // no profiles to update since FLEET VAR could not be populated
return nil
}
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotNil(t, updatedProfile)
assert.Contains(t, updatedProfile.Detail, "FLEET_VAR_"+fleet.FleetVarNDESSCEPChallenge)
assert.Contains(t, updatedProfile.Detail, "update credentials")
assert.NotNil(t, updatedProfile.VariablesUpdatedAt)
assert.Empty(t, targets)
// Password cache full
scepConfig.GetNDESSCEPChallengeFunc = func(ctx context.Context, proxy fleet.NDESSCEPProxyCA) (string, error) {
assert.Equal(t, ndesPassword, proxy.Password)
return "", scep.NewNDESPasswordCacheFullError("NDES error")
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotNil(t, updatedProfile)
assert.Contains(t, updatedProfile.Detail, "FLEET_VAR_"+fleet.FleetVarNDESSCEPChallenge)
assert.Contains(t, updatedProfile.Detail, "cached passwords")
assert.NotNil(t, updatedProfile.VariablesUpdatedAt)
assert.Empty(t, targets)
// Insufficient permissions
scepConfig.GetNDESSCEPChallengeFunc = func(ctx context.Context, proxy fleet.NDESSCEPProxyCA) (string, error) {
assert.Equal(t, ndesPassword, proxy.Password)
return "", scep.NewNDESInsufficientPermissionsError("NDES error")
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotNil(t, updatedProfile)
assert.Contains(t, updatedProfile.Detail, "FLEET_VAR_"+fleet.FleetVarNDESSCEPChallenge)
assert.Contains(t, updatedProfile.Detail, "does not have sufficient permissions")
assert.NotNil(t, updatedProfile.VariablesUpdatedAt)
assert.Empty(t, targets)
// Other NDES challenge error
scepConfig.GetNDESSCEPChallengeFunc = func(ctx context.Context, proxy fleet.NDESSCEPProxyCA) (string, error) {
assert.Equal(t, ndesPassword, proxy.Password)
return "", errors.New("NDES error")
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotNil(t, updatedProfile)
assert.Contains(t, updatedProfile.Detail, "FLEET_VAR_"+fleet.FleetVarNDESSCEPChallenge)
assert.NotContains(t, updatedProfile.Detail, "cached passwords")
assert.NotContains(t, updatedProfile.Detail, "update credentials")
assert.NotNil(t, updatedProfile.VariablesUpdatedAt)
assert.Empty(t, targets)
// NDES challenge
challenge := "ndes-challenge"
scepConfig.GetNDESSCEPChallengeFunc = func(ctx context.Context, proxy fleet.NDESSCEPProxyCA) (string, error) {
assert.Equal(t, ndesPassword, proxy.Password)
return challenge, nil
}
updatedProfile = nil
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
for _, p := range payload {
assert.NotEqual(t, cmdUUID, p.CommandUUID)
}
return nil
}
populateTargets()
ds.BulkUpsertMDMManagedCertificatesFunc = func(ctx context.Context, payload []*fleet.MDMManagedCertificate) error {
require.Len(t, payload, 1)
assert.NotNil(t, payload[0].ChallengeRetrievedAt)
return nil
}
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
assert.Nil(t, updatedProfile)
require.NotEmpty(t, targets)
assert.Len(t, targets, 1)
for profUUID, target := range targets {
assert.NotEqual(t, profUUID, "p1") // new temporary UUID generated for specific host
assert.NotEqual(t, cmdUUID, target.CmdUUID)
assert.Equal(t, []string{hostUUID}, target.EnrollmentIDs)
assert.Equal(t, challenge, string(profileContents[profUUID]))
}
// NDES SCEP proxy URL
profileContents = map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + fleet.FleetVarNDESSCEPProxyURL),
}
expectedURL := "https://test.example.com" + SCEPProxyPath + url.QueryEscape(fmt.Sprintf("%s,%s,NDES", hostUUID, "p1"))
updatedProfile = nil
populateTargets()
ds.BulkUpsertMDMManagedCertificatesFunc = func(ctx context.Context, payload []*fleet.MDMManagedCertificate) error {
assert.Empty(t, payload)
return nil
}
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
assert.Nil(t, updatedProfile)
require.NotEmpty(t, targets)
assert.Len(t, targets, 1)
for profUUID, target := range targets {
assert.NotEqual(t, profUUID, "p1") // new temporary UUID generated for specific host
assert.NotEqual(t, cmdUUID, target.CmdUUID)
assert.Equal(t, []string{hostUUID}, target.EnrollmentIDs)
assert.Equal(t, expectedURL, string(profileContents[profUUID]))
}
// No IdP email found
ds.GetHostEmailsFunc = func(ctx context.Context, hostUUID string, source string) ([]string, error) {
return nil, nil
}
profileContents = map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + fleet.FleetVarHostEndUserEmailIDP),
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotNil(t, updatedProfile)
assert.Contains(t, updatedProfile.Detail, "FLEET_VAR_"+fleet.FleetVarHostEndUserEmailIDP)
assert.Contains(t, updatedProfile.Detail, "no IdP email")
assert.Empty(t, targets)
// IdP email found
email := "user@example.com"
ds.GetHostEmailsFunc = func(ctx context.Context, hostUUID string, source string) ([]string, error) {
return []string{email}, nil
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
assert.Nil(t, updatedProfile)
require.NotEmpty(t, targets)
assert.Len(t, targets, 1)
for profUUID, target := range targets {
assert.NotEqual(t, profUUID, "p1") // new temporary UUID generated for specific host
assert.NotEqual(t, cmdUUID, target.CmdUUID)
assert.Equal(t, []string{hostUUID}, target.EnrollmentIDs)
assert.Equal(t, email, string(profileContents[profUUID]))
}
// Hardware serial
ds.ListHostsLiteByUUIDsFunc = func(ctx context.Context, _ fleet.TeamFilter, uuids []string) ([]*fleet.Host, error) {
assert.Equal(t, []string{hostUUID}, uuids)
return []*fleet.Host{
{HardwareSerial: "serial1"},
}, nil
}
profileContents = map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + fleet.FleetVarHostHardwareSerial),
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
assert.Nil(t, updatedProfile)
require.NotEmpty(t, targets)
assert.Len(t, targets, 1)
for profUUID, target := range targets {
assert.NotEqual(t, profUUID, "p1") // new temporary UUID generated for specific host
assert.NotEqual(t, cmdUUID, target.CmdUUID)
assert.Equal(t, []string{hostUUID}, target.EnrollmentIDs)
assert.Equal(t, "serial1", string(profileContents[profUUID]))
}
// Hardware serial fail
ds.ListHostsLiteByUUIDsFunc = func(ctx context.Context, _ fleet.TeamFilter, uuids []string) ([]*fleet.Host, error) {
assert.Equal(t, []string{hostUUID}, uuids)
return nil, nil
}
updatedProfile = nil
populateTargets()
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotNil(t, updatedProfile)
assert.Contains(t, updatedProfile.Detail, "Unexpected number of hosts (0) for UUID")
assert.Empty(t, targets)
// multiple profiles, multiple hosts
populateTargets = func() {
targets = map[string]*fleet.CmdTarget{
"p1": {CmdUUID: cmdUUID, ProfileIdentifier: "com.add.profile", EnrollmentIDs: []string{hostUUID, "host-2"}}, // fails
"p2": {CmdUUID: cmdUUID, ProfileIdentifier: "com.add.profile2", EnrollmentIDs: []string{hostUUID, "host-3"}}, // works
"p3": {CmdUUID: cmdUUID, ProfileIdentifier: "com.add.profile3", EnrollmentIDs: []string{hostUUID, "host-4"}}, // no variables
}
}
populateTargets()
groupedCAs.NDESSCEP = nil
profileContents = map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + fleet.FleetVarNDESSCEPProxyURL),
"p2": []byte("$FLEET_VAR_" + fleet.FleetVarHostEndUserEmailIDP),
"p3": []byte("no variables"),
}
addProfileToInstall := func(hostUUID, profileUUID, profileIdentifier string) {
hostProfilesToInstallMap[fleet.HostProfileUUID{
HostUUID: hostUUID,
ProfileUUID: profileUUID,
}] = &fleet.MDMAppleBulkUpsertHostProfilePayload{
ProfileUUID: profileUUID,
ProfileIdentifier: profileIdentifier,
HostUUID: hostUUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &fleet.MDMDeliveryPending,
CommandUUID: cmdUUID,
Scope: fleet.PayloadScopeSystem,
}
}
addProfileToInstall(hostUUID, "p1", "com.add.profile")
addProfileToInstall("host-2", "p1", "com.add.profile")
addProfileToInstall(hostUUID, "p2", "com.add.profile2")
addProfileToInstall("host-3", "p2", "com.add.profile2")
addProfileToInstall(hostUUID, "p3", "com.add.profile3")
addProfileToInstall("host-4", "p3", "com.add.profile3")
expectedHostsToFail := []string{hostUUID, "host-2", "host-3"}
ds.UpdateOrDeleteHostMDMAppleProfileFunc = func(ctx context.Context, profile *fleet.HostMDMAppleProfile) error {
updatedProfile = profile
require.NotNil(t, updatedProfile.Status)
assert.Equal(t, fleet.MDMDeliveryFailed, *updatedProfile.Status)
assert.NotEqual(t, cmdUUID, updatedProfile.CommandUUID)
assert.Contains(t, expectedHostsToFail, updatedProfile.HostUUID)
assert.Equal(t, fleet.MDMOperationTypeInstall, updatedProfile.OperationType)
return nil
}
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
for _, p := range payload {
require.NotNil(t, p.Status)
if fleet.MDMDeliveryFailed == *p.Status {
assert.Equal(t, cmdUUID, p.CommandUUID)
} else {
assert.NotEqual(t, cmdUUID, p.CommandUUID)
}
assert.Equal(t, fleet.MDMOperationTypeInstall, p.OperationType)
}
return nil
}
err = preprocessProfileContents(ctx, appCfg, ds, scepConfig, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, groupedCAs)
require.NoError(t, err)
require.NotEmpty(t, targets)
assert.Len(t, targets, 3)
assert.Nil(t, targets["p1"]) // error
assert.Nil(t, targets["p2"]) // renamed
assert.NotNil(t, targets["p3"]) // normal, no variables
for profUUID, target := range targets {
assert.Contains(t, [][]string{{hostUUID}, {"host-3"}, {hostUUID, "host-4"}}, target.EnrollmentIDs)
if profUUID == "p3" {
assert.Equal(t, cmdUUID, target.CmdUUID)
} else {
assert.NotEqual(t, cmdUUID, target.CmdUUID)
}
assert.Contains(t, []string{email, "no variables"}, string(profileContents[profUUID]))
}
}
// TestPreprocessProfileContentsDigiCertUPNMultiHost is a regression test for
// https://github.com/fleetdm/fleet/issues/39324. When the same DigiCert CA is
// used for multiple hosts in a single batch, the CertificateUserPrincipalNames
// slice was shared via a shallow copy. In-place variable substitution for Host 1
// corrupted the cached CA entry, so Host 2 and later hosts received Host 1's
// substituted UPN instead of their own.
func TestPreprocessProfileContentsDigiCertUPNIsUniqueForMultipleHosts(t *testing.T) {
ctx := context.Background()
ctx = license.NewContext(ctx, &fleet.LicenseInfo{Tier: fleet.TierPremium})
logger := slog.New(slog.DiscardHandler)
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = "https://test.example.com"
appCfg.MDM.EnabledAndConfigured = true
ds := new(mock.Store)
svc := scep.NewSCEPConfigService(logger, nil)
const caName = "myCA"
const host1UUID = "host-uuid-1"
const host2UUID = "host-uuid-2"
const host1Serial = "SERIAL-AAA"
const host2Serial = "SERIAL-BBB"
const cmdUUID = "cmd-uuid-1"
// Track which UPNs were sent to GetCertificate per host.
upnByHostUUID := make(map[string]string)
mockDigiCert := &digicert_mock.Service{}
mockDigiCert.GetCertificateFunc = func(ctx context.Context, config fleet.DigiCertCA) (*fleet.DigiCertCertificate, error) {
// The UPN in config should have been substituted with each host's own
// hardware serial. Record it so we can assert correctness later.
require.Len(t, config.CertificateUserPrincipalNames, 1)
upn := config.CertificateUserPrincipalNames[0]
// Determine which host this call is for by checking which serial is in the UPN.
switch {
case strings.Contains(upn, host1Serial):
upnByHostUUID[host1UUID] = upn
case strings.Contains(upn, host2Serial):
upnByHostUUID[host2UUID] = upn
default:
t.Errorf("GetCertificate called with unexpected UPN %q", upn)
}
now := time.Now()
return &fleet.DigiCertCertificate{
PfxData: []byte("fake-pfx"),
Password: "fake-password",
NotValidBefore: now,
NotValidAfter: now.Add(365 * 24 * time.Hour),
SerialNumber: upn, // reuse upn as serial for easy tracing
}, nil
}
// Both hosts share the same profile UUID but are separate enrollment IDs.
targets := map[string]*fleet.CmdTarget{
"p1": {
CmdUUID: cmdUUID,
ProfileIdentifier: "com.apple.security.pkcs12",
EnrollmentIDs: []string{host1UUID, host2UUID},
},
}
pending := fleet.MDMDeliveryPending
hostProfilesToInstallMap := map[fleet.HostProfileUUID]*fleet.MDMAppleBulkUpsertHostProfilePayload{
{HostUUID: host1UUID, ProfileUUID: "p1"}: {
ProfileUUID: "p1",
ProfileIdentifier: "com.apple.security.pkcs12",
HostUUID: host1UUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &pending,
CommandUUID: cmdUUID,
Scope: fleet.PayloadScopeSystem,
},
{HostUUID: host2UUID, ProfileUUID: "p1"}: {
ProfileUUID: "p1",
ProfileIdentifier: "com.apple.security.pkcs12",
HostUUID: host2UUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &pending,
CommandUUID: cmdUUID,
Scope: fleet.PayloadScopeSystem,
},
}
// Profile contains both DigiCert fleet variables.
profileContents := map[string]mobileconfig.Mobileconfig{
"p1": []byte("$FLEET_VAR_" + string(fleet.FleetVarDigiCertPasswordPrefix) + caName + " $FLEET_VAR_" + string(fleet.FleetVarDigiCertDataPrefix) + caName),
}
// DigiCert CA whose UPN contains the hardware serial variable.
groupedCAs := &fleet.GroupedCertificateAuthorities{
DigiCert: []fleet.DigiCertCA{
{
Name: caName,
URL: "https://digicert.example.com",
APIToken: "api_token",
ProfileID: "profile_id",
CertificateCommonName: "common_name",
CertificateUserPrincipalNames: []string{"$FLEET_VAR_" + string(fleet.FleetVarHostHardwareSerial) + "@example.com"},
CertificateSeatID: "seat_id",
},
},
}
// Mock datastore: return each host's own hardware serial when queried.
hostsByUUID := map[string]*fleet.Host{
host1UUID: {ID: 1, UUID: host1UUID, HardwareSerial: host1Serial, Platform: "darwin"},
host2UUID: {ID: 2, UUID: host2UUID, HardwareSerial: host2Serial, Platform: "darwin"},
}
ds.ListHostsLiteByUUIDsFunc = func(ctx context.Context, _ fleet.TeamFilter, uuids []string) ([]*fleet.Host, error) {
var hosts []*fleet.Host
for _, uuid := range uuids {
if h, ok := hostsByUUID[uuid]; ok {
hosts = append(hosts, h)
}
}
return hosts, nil
}
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
return nil
}
ds.BulkUpsertMDMManagedCertificatesFunc = func(ctx context.Context, payload []*fleet.MDMManagedCertificate) error {
return nil
}
err := preprocessProfileContents(ctx, appCfg, ds, svc, mockDigiCert, logger, targets, profileContents, hostProfilesToInstallMap, make(map[string]string), groupedCAs)
require.NoError(t, err)
// Both hosts must have received GetCertificate calls with their own serial.
require.True(t, mockDigiCert.GetCertificateFuncInvoked, "GetCertificate was never called")
require.Contains(t, upnByHostUUID, host1UUID, "GetCertificate was not called for host 1")
require.Contains(t, upnByHostUUID, host2UUID, "GetCertificate was not called for host 2")
assert.Equal(t, host1Serial+"@example.com", upnByHostUUID[host1UUID], "host 1 UPN should contain its own serial")
assert.Equal(t, host2Serial+"@example.com", upnByHostUUID[host2UUID], "host 2 UPN should contain its own serial")
}
func TestPreprocessProfileContentsEndUserIDP(t *testing.T) {
ctx := context.Background()
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = "https://test.example.com"
appCfg.MDM.EnabledAndConfigured = true
ds := new(mock.Store)
svc := scep.NewSCEPConfigService(logger, nil)
digiCertService := digicert.NewService(digicert.WithLogger(logger))
hostUUID := "host-1"
cmdUUID := "cmd-1"
var targets map[string]*fleet.CmdTarget
// this is a func to re-create it each time because calling the preprocess function modifies this
populateTargets := func() {
targets = map[string]*fleet.CmdTarget{
"p1": {CmdUUID: cmdUUID, ProfileIdentifier: "com.add.profile", EnrollmentIDs: []string{hostUUID}},
}
}
hostProfilesToInstallMap := map[fleet.HostProfileUUID]*fleet.MDMAppleBulkUpsertHostProfilePayload{
{HostUUID: hostUUID, ProfileUUID: "p1"}: {
ProfileUUID: "p1",
ProfileIdentifier: "com.add.profile",
HostUUID: hostUUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &fleet.MDMDeliveryPending,
CommandUUID: cmdUUID,
},
}
userEnrollmentsToHostUUIDsMap := make(map[string]string)
var updatedPayload *fleet.MDMAppleBulkUpsertHostProfilePayload
var expectedStatus fleet.MDMDeliveryStatus
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
require.Len(t, payload, 1)
updatedPayload = payload[0]
require.NotNil(t, updatedPayload.Status)
assert.Equal(t, expectedStatus, *updatedPayload.Status)
// cmdUUID was replaced by a new unique command on success
assert.NotEqual(t, cmdUUID, updatedPayload.CommandUUID)
assert.Equal(t, hostUUID, updatedPayload.HostUUID)
assert.Equal(t, fleet.MDMOperationTypeInstall, updatedPayload.OperationType)
return nil
}
ds.HostIDsByIdentifierFunc = func(ctx context.Context, filter fleet.TeamFilter, idents []string) ([]uint, error) {
require.Len(t, idents, 1)
require.Equal(t, hostUUID, idents[0])
return []uint{1}, nil
}
var updatedProfile *fleet.HostMDMAppleProfile
ds.UpdateOrDeleteHostMDMAppleProfileFunc = func(ctx context.Context, profile *fleet.HostMDMAppleProfile) error {
updatedProfile = profile
require.NotNil(t, profile.Status)
assert.Equal(t, expectedStatus, *profile.Status)
return nil
}
ds.GetAllCertificateAuthoritiesFunc = func(ctx context.Context, includeSecrets bool) ([]*fleet.CertificateAuthority, error) {
return []*fleet.CertificateAuthority{}, nil
}
ds.ListHostDeviceMappingFunc = func(ctx context.Context, id uint) ([]*fleet.HostDeviceMapping, error) {
return nil, nil
}
cases := []struct {
desc string
profileContent string
expectedStatus fleet.MDMDeliveryStatus
setup func()
assert func(output string)
}{
{
desc: "username only scim",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsername),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "user1@example.com", output)
},
},
{
desc: "username local part only scim",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsernameLocalPart),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "user1", output)
},
},
{
desc: "groups only scim",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPGroups),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
Groups: []fleet.ScimUserGroup{{DisplayName: "a"}, {DisplayName: "b"}},
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "a,b", output)
},
},
{
desc: "multiple times username only scim",
profileContent: strings.Repeat("${FLEET_VAR_"+string(fleet.FleetVarHostEndUserIDPUsername)+"}", 3),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "user1@example.comuser1@example.comuser1@example.com", output)
},
},
{
desc: "all 3 vars with scim",
profileContent: "${FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsername) + "}${FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsernameLocalPart) + "}${FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPGroups) + "}",
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
Groups: []fleet.ScimUserGroup{{DisplayName: "a"}, {DisplayName: "b"}},
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "user1@example.comuser1a,b", output)
},
},
{
desc: "username no scim, with idp",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsername),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "idp@example.com",
Groups: []fleet.ScimUserGroup{{DisplayName: "a"}, {DisplayName: "b"}},
}, nil
}
ds.ListHostDeviceMappingFunc = func(ctx context.Context, id uint) ([]*fleet.HostDeviceMapping, error) {
return []*fleet.HostDeviceMapping{
{
Email: "other@example.com", Source: fleet.DeviceMappingGoogleChromeProfiles,
},
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "idp@example.com", output)
},
},
{
desc: "username scim and idp",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsername),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
ds.ListHostDeviceMappingFunc = func(ctx context.Context, id uint) ([]*fleet.HostDeviceMapping, error) {
return []*fleet.HostDeviceMapping{
{
Email: "other@example.com", Source: fleet.DeviceMappingGoogleChromeProfiles,
},
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "user1@example.com", output)
},
},
{
desc: "username, no idp user",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsername),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{}, nil
}
ds.ListHostDeviceMappingFunc = func(ctx context.Context, id uint) ([]*fleet.HostDeviceMapping, error) {
return []*fleet.HostDeviceMapping{
{
Email: "other@example.com", Source: fleet.DeviceMappingGoogleChromeProfiles,
},
}, nil
}
},
assert: func(output string) {
assert.Len(t, targets, 0) // target is not present
assert.Contains(t, updatedProfile.Detail, "There is no IdP username for this host. Fleet couldn't populate $FLEET_VAR_HOST_END_USER_IDP_USERNAME.")
},
},
{
desc: "username local part, no idp user",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPUsernameLocalPart),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{}, nil
}
ds.ListHostDeviceMappingFunc = func(ctx context.Context, id uint) ([]*fleet.HostDeviceMapping, error) {
return []*fleet.HostDeviceMapping{
{
Email: "other@example.com", Source: fleet.DeviceMappingGoogleChromeProfiles,
},
}, nil
}
},
assert: func(output string) {
assert.Len(t, targets, 0) // target is not present
assert.Contains(t, updatedProfile.Detail, "There is no IdP username for this host. Fleet couldn't populate $FLEET_VAR_HOST_END_USER_IDP_USERNAME_LOCAL_PART.")
},
},
{
desc: "groups, no idp user",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPGroups),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{}, nil
}
},
assert: func(output string) {
assert.Len(t, targets, 0) // target is not present
assert.Contains(t, updatedProfile.Detail, "There are no IdP groups for this host. Fleet couldn't populate $FLEET_VAR_HOST_END_USER_IDP_GROUPS.")
},
},
{
desc: "department, no idp user",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPDepartment),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{}, nil
}
},
assert: func(output string) {
assert.Len(t, targets, 0) // target is not present
assert.Contains(t, updatedProfile.Detail, "There is no IdP department for this host. Fleet couldn't populate $FLEET_VAR_HOST_END_USER_IDP_DEPARTMENT.")
},
},
{
desc: "groups with user groups, user has no groups",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPGroups),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
},
assert: func(output string) {
assert.Len(t, targets, 0) // target is not present
assert.Contains(t, updatedProfile.Detail, "There are no IdP groups for this host. Fleet couldn't populate $FLEET_VAR_HOST_END_USER_IDP_GROUPS.")
},
},
{
desc: "profile with department, user has department",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPDepartment),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
Department: ptr.String("Engineering"),
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "Engineering", output)
},
},
{
desc: "profile with department, user has no department",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPDepartment),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
},
assert: func(output string) {
assert.Len(t, targets, 0) // target is not present
assert.Contains(t, updatedProfile.Detail, "There is no IdP department for this host. Fleet couldn't populate $FLEET_VAR_HOST_END_USER_IDP_DEPARTMENT.")
},
},
{
desc: "profile with full name, user has full name",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPFullname),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
GivenName: ptr.String("First"),
FamilyName: ptr.String("Last"),
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "First Last", output)
},
},
{
desc: "profile with full name, user only has given name",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPFullname),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
GivenName: ptr.String("First"),
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "First", output)
},
},
{
desc: "profile with full name, user only has family name",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPFullname),
expectedStatus: fleet.MDMDeliveryPending,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
FamilyName: ptr.String("Last"),
}, nil
}
},
assert: func(output string) {
assert.Empty(t, updatedPayload.Detail) // no error detail
assert.Len(t, targets, 1) // target is still present
require.Equal(t, "Last", output)
},
},
{
desc: "profile with full name, user has no full name value",
profileContent: "$FLEET_VAR_" + string(fleet.FleetVarHostEndUserIDPFullname),
expectedStatus: fleet.MDMDeliveryFailed,
setup: func() {
ds.ScimUserByHostIDFunc = func(ctx context.Context, hostID uint) (*fleet.ScimUser, error) {
require.EqualValues(t, 1, hostID)
return &fleet.ScimUser{
UserName: "user1@example.com",
}, nil
}
},
assert: func(output string) {
assert.Contains(t, updatedProfile.Detail, fmt.Sprintf("There is no IdP full name for this host. Fleet couldn't populate $FLEET_VAR_%s.", fleet.FleetVarHostEndUserIDPFullname))
assert.Len(t, targets, 0)
},
},
}
for _, c := range cases {
t.Run(c.desc, func(t *testing.T) {
c.setup()
profileContents := map[string]mobileconfig.Mobileconfig{
"p1": []byte(c.profileContent),
}
populateTargets()
expectedStatus = c.expectedStatus
updatedPayload = nil
updatedProfile = nil
err := preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, hostProfilesToInstallMap, userEnrollmentsToHostUUIDsMap, nil)
require.NoError(t, err)
var output string
if expectedStatus == fleet.MDMDeliveryFailed {
require.Nil(t, updatedPayload)
require.NotNil(t, updatedProfile)
} else {
require.NotNil(t, updatedPayload)
require.Nil(t, updatedProfile)
output = string(profileContents[updatedPayload.CommandUUID])
}
c.assert(output)
})
}
}
func TestPreprocessProfileContentsPSSORegistrationToken(t *testing.T) {
ctx := context.Background()
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = "https://test.example.com"
appCfg.MDM.EnabledAndConfigured = true
svc := scep.NewSCEPConfigService(logger, nil)
digiCertService := digicert.NewService(digicert.WithLogger(logger))
const hostUUID = "host-1"
const cmdUUID = "cmd-1"
placeholder := "$" + fleet.HostSecretPrefix + fleet.HostSecretPSSODeviceRegistrationToken
newHostProfilesMap := func() map[fleet.HostProfileUUID]*fleet.MDMAppleBulkUpsertHostProfilePayload {
m := make(map[fleet.HostProfileUUID]*fleet.MDMAppleBulkUpsertHostProfilePayload, 1)
m[fleet.HostProfileUUID{HostUUID: hostUUID, ProfileUUID: "p1"}] = &fleet.MDMAppleBulkUpsertHostProfilePayload{
ProfileUUID: "p1",
ProfileIdentifier: "com.fleetdm.platformsso",
HostUUID: hostUUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &fleet.MDMDeliveryPending,
CommandUUID: cmdUUID,
Scope: fleet.PayloadScopeSystem,
}
return m
}
t.Run("only variable short-circuits the per-host split", func(t *testing.T) {
ds := new(mock.Store)
bulkUpsertCalled := false
ds.BulkUpsertMDMAppleHostProfilesFunc = func(_ context.Context, _ []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
bulkUpsertCalled = true
return nil
}
targets := map[string]*fleet.CmdTarget{
"p1": {CmdUUID: cmdUUID, ProfileIdentifier: "com.fleetdm.platformsso", EnrollmentIDs: []string{hostUUID}},
}
profileContents := map[string]mobileconfig.Mobileconfig{
"p1": []byte("" + fleet.FleetVarPSSODeviceRegistrationToken.WithPrefix() + ""),
}
err := preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, newHostProfilesMap(), make(map[string]string), &fleet.GroupedCertificateAuthorities{})
require.NoError(t, err)
// The original target is preserved (no per-host fan-out, no new temp UUIDs).
require.Len(t, targets, 1)
require.Contains(t, targets, "p1")
require.Equal(t, cmdUUID, targets["p1"].CmdUUID)
require.False(t, bulkUpsertCalled, "host profiles should not be re-keyed for the short-circuited profile")
// The variable resolved to the host-secret placeholder on the shared content.
require.Equal(t, ""+placeholder+"", string(profileContents["p1"]))
require.NotContains(t, string(profileContents["p1"]), "FLEET_VAR_")
})
t.Run("multiple hosts share placeholder without per-host fan-out", func(t *testing.T) {
const host2UUID = "host-2"
const host3UUID = "host-3"
ds := new(mock.Store)
bulkUpsertCalled := false
ds.BulkUpsertMDMAppleHostProfilesFunc = func(_ context.Context, _ []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
bulkUpsertCalled = true
return nil
}
enrollmentIDs := []string{hostUUID, host2UUID, host3UUID}
targets := map[string]*fleet.CmdTarget{
"p1": {CmdUUID: cmdUUID, ProfileIdentifier: "com.fleetdm.platformsso", EnrollmentIDs: enrollmentIDs},
}
profileContents := map[string]mobileconfig.Mobileconfig{
"p1": []byte("" + fleet.FleetVarPSSODeviceRegistrationToken.WithPrefix() + ""),
}
multiHostProfilesMap := make(map[fleet.HostProfileUUID]*fleet.MDMAppleBulkUpsertHostProfilePayload)
for _, hUUID := range enrollmentIDs {
multiHostProfilesMap[fleet.HostProfileUUID{HostUUID: hUUID, ProfileUUID: "p1"}] = &fleet.MDMAppleBulkUpsertHostProfilePayload{
ProfileUUID: "p1",
ProfileIdentifier: "com.fleetdm.platformsso",
HostUUID: hUUID,
OperationType: fleet.MDMOperationTypeInstall,
Status: &fleet.MDMDeliveryPending,
CommandUUID: cmdUUID,
Scope: fleet.PayloadScopeSystem,
}
}
err := preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, multiHostProfilesMap, make(map[string]string), &fleet.GroupedCertificateAuthorities{})
require.NoError(t, err)
// Still one target — no per-host fan-out regardless of host count.
require.Len(t, targets, 1)
require.Contains(t, targets, "p1")
require.Equal(t, cmdUUID, targets["p1"].CmdUUID)
// All enrollment IDs remain in the single shared target.
require.ElementsMatch(t, enrollmentIDs, targets["p1"].EnrollmentIDs)
require.False(t, bulkUpsertCalled, "host profiles should not be re-keyed for the short-circuited profile")
// Single shared profile content with the placeholder — no per-host copies.
require.Equal(t, ""+placeholder+"", string(profileContents["p1"]))
require.NotContains(t, string(profileContents["p1"]), "FLEET_VAR_")
})
t.Run("mixed with a host-specific variable still fans out and keeps the placeholder", func(t *testing.T) {
ds := new(mock.Store)
ds.BulkUpsertMDMAppleHostProfilesFunc = func(_ context.Context, _ []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
return nil
}
targets := map[string]*fleet.CmdTarget{
"p1": {CmdUUID: cmdUUID, ProfileIdentifier: "com.fleetdm.platformsso", EnrollmentIDs: []string{hostUUID}},
}
profileContents := map[string]mobileconfig.Mobileconfig{
"p1": []byte("" + fleet.FleetVarPSSODeviceRegistrationToken.WithPrefix() + "" + fleet.FleetVarHostUUID.WithPrefix() + ""),
}
err := preprocessProfileContents(ctx, appCfg, ds, svc, digiCertService, logger, targets, profileContents, newHostProfilesMap(), make(map[string]string), &fleet.GroupedCertificateAuthorities{})
require.NoError(t, err)
// The original target is replaced by a per-host target.
require.NotContains(t, targets, "p1")
require.Len(t, targets, 1)
var tempUUID string
for k := range targets {
tempUUID = k
}
hostContents := string(profileContents[tempUUID])
require.Contains(t, hostContents, placeholder)
require.Contains(t, hostContents, hostUUID)
require.NotContains(t, hostContents, "FLEET_VAR_")
})
}