Add Windows admin account config (#49863)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48720 

Subtask of https://github.com/fleetdm/fleet/issues/43488
This PR only adds the Windows config, and doesn't mess with macOS
configs.

# Checklist for submitter

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

## New Fleet configuration settings

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added managed local account settings for Windows to app and team
configuration, including GitOps support.
* Exposed an explicit enabled/disabled toggle in configuration output
and Fleet controls.
* Added licensing and Windows MDM prerequisites for enabling the
setting.

* **Bug Fixes**
* Managed local account enable/disable actions are now correctly
persisted and declaratively applied.
* Activity feed messages now display platform-specific (macOS vs
Windows) wording.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Victor Lyuboslavsky
2026-07-28 12:10:33 -05:00
committed by GitHub
parent 4b8a8435af
commit ffc85a42ae
38 changed files with 510 additions and 110 deletions
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -901,7 +901,8 @@ func testTeamsMDMConfig(t *testing.T, ds *Datastore) {
EndUserLocalAccountType: optjson.SetString("admin"),
},
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.SetSlice([]fleet.MDMProfileSpec{{Path: "foo"}, {Path: "bar"}}),
CustomSettings: optjson.SetSlice([]fleet.MDMProfileSpec{{Path: "foo"}, {Path: "bar"}}),
ManagedLocalAccountSettings: fleet.ManagedLocalAccountSettings{Enabled: optjson.SetBool(false)},
},
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.SetSlice([]fleet.MDMProfileSpec{{Path: "baz"}, {Path: "qux"}}),
+2
View File
@@ -724,6 +724,7 @@ func (a ActivityTypeViewedManagedLocalAccount) HostIDs() []uint {
type ActivityTypeEnabledManagedLocalAccount struct {
TeamID *uint `json:"team_id" renameto:"fleet_id"`
TeamName *string `json:"team_name" renameto:"fleet_name"`
Platform string `json:"platform,omitempty"`
}
func (a ActivityTypeEnabledManagedLocalAccount) ActivityName() string {
@@ -733,6 +734,7 @@ func (a ActivityTypeEnabledManagedLocalAccount) ActivityName() string {
type ActivityTypeDisabledManagedLocalAccount struct {
TeamID *uint `json:"team_id" renameto:"fleet_id"`
TeamName *string `json:"team_name" renameto:"fleet_name"`
Platform string `json:"platform,omitempty"`
}
func (a ActivityTypeDisabledManagedLocalAccount) ActivityName() string {
+22
View File
@@ -2116,10 +2116,32 @@ func (v *Version) AuthzType() string {
return "version"
}
// ManagedLocalAccountSettings configures the hidden managed local admin account for one platform.
// Future fields (username, password policy) land here.
type ManagedLocalAccountSettings struct {
Enabled optjson.Bool `json:"enabled"`
}
// MarshalJSON defaults the enabled flag to false when it was never set, so every serialization
// path (API responses, stored config JSON, spec exports, GitOps payloads) emits a boolean
// rather than null. Request payloads are unaffected: clients send raw JSON, not this struct.
func (m ManagedLocalAccountSettings) MarshalJSON() ([]byte, error) {
if !m.Enabled.Valid {
m.Enabled = optjson.SetBool(false)
}
// the alias type has no methods, so marshaling it avoids infinite recursion into this MarshalJSON
type alias ManagedLocalAccountSettings
return json.Marshal(alias(m))
}
type WindowsSettings struct {
// NOTE: These are only present here for informational purposes.
// (The source of truth for profiles is in MySQL.)
CustomSettings optjson.Slice[MDMProfileSpec] `json:"custom_settings" renameto:"configuration_profiles"`
// ManagedLocalAccountSettings configures the hidden managed local admin account created by
// fleetd on Windows hosts during Autopilot/OOBE enrollment.
ManagedLocalAccountSettings ManagedLocalAccountSettings `json:"managed_local_account_settings"`
}
func (ws WindowsSettings) GetMDMProfileSpecs() []MDMProfileSpec {
+28
View File
@@ -912,3 +912,31 @@ func TestMacOSSetupValidate(t *testing.T) {
}
})
}
// TestManagedLocalAccountSettingsMarshalDefaults verifies every marshal/save path defaults the
// Windows managed local account toggle to enabled: false and preserves a set value.
func TestManagedLocalAccountSettingsMarshalDefaults(t *testing.T) {
windowsSettings := func(b []byte) any {
var out map[string]any
require.NoError(t, json.Unmarshal(b, &out))
return out["mdm"].(map[string]any)["windows_settings"].(map[string]any)["managed_local_account_settings"]
}
marshaled := func(v any) any {
b, err := json.Marshal(v)
require.NoError(t, err)
return windowsSettings(b)
}
var ac AppConfig
require.Equal(t, map[string]any{"enabled": false}, marshaled(ac))
ac.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled = optjson.SetBool(true)
require.Equal(t, map[string]any{"enabled": true}, marshaled(ac))
team := Team{ID: 1, Name: "t1"}
require.Equal(t, map[string]any{"enabled": false}, marshaled(team))
// the DB save path (TeamConfig.Value) applies the same default
v, err := team.Config.Value()
require.NoError(t, err)
require.Equal(t, map[string]any{"enabled": false}, windowsSettings(v.([]byte)))
}
+1
View File
@@ -41,6 +41,7 @@ const (
OSUpdatesAlreadyConfiguredErrorMessage = "Couldn't add profile. OS updates are already configured. Remove the OS updates settings first."
CouldNotUpdateAppleOSSettingsWithCustomProfileErrorMessage = "Couldn't update OS updates settings. A custom OS updates declaration profile already exists. Remove the custom profile first."
CouldNotUpdateWindowsOSSettingsWithCustomProfileErrorMessage = "Couldn't update OS updates settings. A custom OS updates profile already exists. Remove the custom profile first."
WindowsMDMNotTurnedOnMessage = `Windows MDM isnt turned on. This can be enabled by setting "controls.windows_enabled_and_configured: true" in the default configuration. Visit https://fleetdm.com/guides/windows-mdm-setup and https://fleetdm.com/docs/configuration/yaml-files#controls to learn more about enabling MDM.`
)
// FleetVarName represents the name of a Fleet variable (without the FLEET_VAR_ prefix).
+9
View File
@@ -103,6 +103,15 @@ type TeamPayloadMDM struct {
MacOSSetup *MacOSSetup `json:"macos_setup"`
HostNameTemplate optjson.String `json:"name_template"`
// WindowsSettings exposes only the managed local account surface on the team PATCH endpoint;
// configuration profiles are managed through their own endpoints.
WindowsSettings *TeamPayloadWindowsSettings `json:"windows_settings"`
}
// TeamPayloadWindowsSettings is the subset of windows_settings fields settable via the team PATCH endpoint.
type TeamPayloadWindowsSettings struct {
ManagedLocalAccountSettings ManagedLocalAccountSettings `json:"managed_local_account_settings"`
}
// Team is the data representation for the "Team" concept (group of hosts and
+36 -3
View File
@@ -877,6 +877,17 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
appConfig.MDM.MacOSSetup.EndUserLocalAccountType = oldAppConfig.MDM.MacOSSetup.EndUserLocalAccountType
}
// windows_settings.managed_local_account_settings.enabled: like EnableDiskEncryption above, an explicit JSON null
// means "not provided": keep the old value rather than persisting an invalid optjson state.
if !oldAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled.Valid {
oldAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled = optjson.SetBool(false)
}
if newAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled.Valid {
appConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled = newAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled
} else {
appConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled = oldAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled
}
if appConfig.MDM.MacOSSetup.ManualAgentInstall.Valid && appConfig.MDM.MacOSSetup.ManualAgentInstall.Value {
if !lic.IsPremium() {
invalid.Append("setup_experience.macos_manual_agent_install", ErrMissingLicense.Error())
@@ -1540,15 +1551,27 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
if oldAppConfig.MDM.MacOSSetup.EnableManagedLocalAccount.Value != appConfig.MDM.MacOSSetup.EnableManagedLocalAccount.Value {
var act fleet.ActivityDetails
if appConfig.MDM.MacOSSetup.EnableManagedLocalAccount.Value {
act = fleet.ActivityTypeEnabledManagedLocalAccount{}
act = fleet.ActivityTypeEnabledManagedLocalAccount{Platform: "darwin"}
} else {
act = fleet.ActivityTypeDisabledManagedLocalAccount{}
act = fleet.ActivityTypeDisabledManagedLocalAccount{Platform: "darwin"}
}
if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), act); err != nil {
return nil, ctxerr.Wrap(ctx, err, "create activity for macos enable managed local account change")
}
}
if oldAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value != appConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value {
var act fleet.ActivityDetails
if appConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value {
act = fleet.ActivityTypeEnabledManagedLocalAccount{Platform: "windows"}
} else {
act = fleet.ActivityTypeDisabledManagedLocalAccount{Platform: "windows"}
}
if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), act); err != nil {
return nil, ctxerr.Wrap(ctx, err, "create activity for windows enable managed local account change")
}
}
mdmSSOSettingsChanged := oldAppConfig.MDM.EndUserAuthentication.SSOProviderSettings !=
appConfig.MDM.EndUserAuthentication.SSOProviderSettings
serverURLChanged := oldAppConfig.ServerSettings.ServerURL != appConfig.ServerSettings.ServerURL
@@ -1881,6 +1904,10 @@ func (svc *Service) validateMDM(
if mdm.MacOSSetup.ManualAgentInstall.Valid && oldMdm.MacOSSetup.ManualAgentInstall.Value != mdm.MacOSSetup.ManualAgentInstall.Value && !lic.IsPremium() {
invalid.Append("setup_experience.macos_manual_agent_install", ErrMissingLicense.Error())
}
if mdm.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value &&
mdm.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value != oldMdm.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value && !lic.IsPremium() {
invalid.Append("windows_settings.managed_local_account_settings.enabled", ErrMissingLicense.Error())
}
if mdm.WindowsMigrationEnabled && !lic.IsPremium() {
invalid.Append("windows_migration_enabled", ErrMissingLicense.Error())
}
@@ -1949,7 +1976,13 @@ func (svc *Service) validateMDM(
len(mdm.WindowsSettings.CustomSettings.Value) > 0 &&
!fleet.MDMProfileSpecsMatch(mdm.WindowsSettings.CustomSettings.Value, oldMdm.WindowsSettings.CustomSettings.Value) {
invalid.Append("windows_settings.configuration_profiles",
`Couldnt edit windows_settings.configuration_profiles. Windows MDM isnt turned on. This can be enabled by setting "controls.windows_enabled_and_configured: true" in the default configuration. Visit https://fleetdm.com/guides/windows-mdm-setup and https://fleetdm.com/docs/configuration/yaml-files#controls to learn more about enabling MDM.`)
"Couldnt edit windows_settings.configuration_profiles. "+fleet.WindowsMDMNotTurnedOnMessage)
}
if mdm.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value &&
!oldMdm.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value {
invalid.Append("windows_settings.managed_local_account_settings.enabled",
"Couldnt enable windows_settings.managed_local_account_settings. "+fleet.WindowsMDMNotTurnedOnMessage)
}
}
fleet.ValidateMDMProfileSpecs(invalid, "windows", mdm.WindowsSettings.CustomSettings.Value)
+101 -37
View File
@@ -1225,7 +1225,8 @@ func TestMDMConfig(t *testing.T) {
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
ManagedLocalAccountSettings: fleet.ManagedLocalAccountSettings{Enabled: optjson.SetBool(false)},
},
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
@@ -3042,57 +3043,121 @@ func TestModifyAppConfigClearBootstrapPackageAlreadyDeleted(t *testing.T) {
require.NoError(t, err)
}
// TestModifyAppConfigManagedLocalAccount covers the no-team (team 0) path
// through PATCH /config, which ModifyTeam doesn't handle.
// TestModifyAppConfigManagedLocalAccount covers the no-team (team 0) path through PATCH /config for both managed
// local account platform toggles, which ModifyTeam doesn't handle.
func TestModifyAppConfigManagedLocalAccount(t *testing.T) {
admin := &fleet.User{GlobalRole: new(fleet.RoleAdmin)}
testCases := []struct {
name string
mdmConfigured bool
startEnabled bool
patch string
wantErr string
wantActivity string
name string
freeTier bool
appleMDMOff bool
windowsMDMOff bool
startMacOS bool
startWindows bool
patch string
wantErr string
wantActivities []string
wantWindowsEnabled bool
}{
{
name: "MDM not configured rejects the change",
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": true}}}`,
wantErr: "setup_experience.enable_managed_local_account",
name: "macOS: enabling managed local account requires Apple MDM",
appleMDMOff: true,
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": true}}}`,
wantErr: "setup_experience.enable_managed_local_account",
},
{
name: "enabling emits the enabled activity",
mdmConfigured: true,
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": true}}}`,
wantActivity: fleet.ActivityTypeEnabledManagedLocalAccount{}.ActivityName(),
name: "macOS: enabling managed local account emits the enabled activity",
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": true}}}`,
wantActivities: []string{"enabled_managed_local_account:darwin"},
},
{
name: "disabling emits the disabled activity",
mdmConfigured: true,
startEnabled: true,
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": false}}}`,
wantActivity: fleet.ActivityTypeDisabledManagedLocalAccount{}.ActivityName(),
name: "macOS: disabling managed local account emits the disabled activity",
startMacOS: true,
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": false}}}`,
wantActivities: []string{"disabled_managed_local_account:darwin"},
},
{
name: "no-op change emits no activity",
mdmConfigured: true,
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": false}}}`,
name: "macOS: managed local account no-op change emits no activity",
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": false}}}`,
},
{
name: "windows: enabling managed local account persists and fires activity",
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": true}}}}`,
wantActivities: []string{"enabled_managed_local_account:windows"},
wantWindowsEnabled: true,
},
{
name: "windows: disabling managed local account persists and fires activity",
startWindows: true,
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": false}}}}`,
wantActivities: []string{"disabled_managed_local_account:windows"},
},
{
name: "windows: null managed local account enabled means not provided",
startWindows: true,
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": null}}}}`,
wantWindowsEnabled: true,
},
{
name: "windows: managed local account no-op change fires no activity",
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": false}}}}`,
},
{
name: "enabling managed local account on both platforms in one payload fires one activity per platform",
patch: `{"mdm": {"macos_setup": {"enable_managed_local_account": true}, "windows_settings": {"managed_local_account_settings": {"enabled": true}}}}`,
wantActivities: []string{"enabled_managed_local_account:darwin", "enabled_managed_local_account:windows"},
wantWindowsEnabled: true,
},
{
name: "windows: enabling managed local account requires premium",
freeTier: true,
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": true}}}}`,
wantErr: "missing or invalid license",
},
{
name: "windows: disabling managed local account is allowed without premium (license downgrade)",
freeTier: true,
startWindows: true,
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": false}}}}`,
wantActivities: []string{"disabled_managed_local_account:windows"},
},
{
name: "windows: enabling managed local account requires Windows MDM",
windowsMDMOff: true,
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": true}}}}`,
wantErr: "windows_settings.managed_local_account_settings",
},
{
name: "windows: managed local account with end_user_local_account_type rejected",
patch: `{"mdm": {"windows_settings": {"managed_local_account_settings": {"enabled": true}, "end_user_local_account_type": "admin"}}}`,
wantErr: "end_user_local_account_type",
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ds := new(mock.Store)
opts := &TestServerOpts{License: &fleet.LicenseInfo{Tier: fleet.TierPremium}}
svc, ctx := newTestService(t, ds, nil, nil, opts)
tier := fleet.TierPremium
if tt.freeTier {
tier = fleet.TierFree
}
opts := &TestServerOpts{License: &fleet.LicenseInfo{Tier: tier}}
// keeping Windows MDM enabled across the PATCH requires a configured WSTEP cert/key pair
cfg := config.TestConfig()
cfg.MDM.WindowsWSTEPIdentityCert = "testdata/server.pem"
cfg.MDM.WindowsWSTEPIdentityKey = "testdata/server.key"
svc, ctx := newTestServiceWithConfig(t, ds, cfg, nil, nil, opts)
ctx = viewer.NewContext(ctx, viewer.Viewer{User: admin})
dsAppConfig := &fleet.AppConfig{
OrgInfo: fleet.OrgInfo{OrgName: "Test"},
ServerSettings: fleet.ServerSettings{ServerURL: "https://example.org"},
}
dsAppConfig.MDM.EnabledAndConfigured = tt.mdmConfigured
dsAppConfig.MDM.MacOSSetup.EnableManagedLocalAccount = optjson.SetBool(tt.startEnabled)
dsAppConfig.MDM.EnabledAndConfigured = !tt.appleMDMOff
dsAppConfig.MDM.WindowsEnabledAndConfigured = !tt.windowsMDMOff
dsAppConfig.MDM.MacOSSetup.EnableManagedLocalAccount = optjson.SetBool(tt.startMacOS)
dsAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled = optjson.SetBool(tt.startWindows)
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) { return dsAppConfig, nil }
ds.SaveAppConfigFunc = func(ctx context.Context, conf *fleet.AppConfig) error {
@@ -3105,9 +3170,11 @@ func TestModifyAppConfigManagedLocalAccount(t *testing.T) {
var gotActivities []string
opts.ActivityMock.NewActivityFunc = func(_ context.Context, _ *activity_api.User, act activity_api.ActivityDetails) error {
switch act.(type) {
case fleet.ActivityTypeEnabledManagedLocalAccount, fleet.ActivityTypeDisabledManagedLocalAccount:
gotActivities = append(gotActivities, act.ActivityName())
switch a := act.(type) {
case fleet.ActivityTypeEnabledManagedLocalAccount:
gotActivities = append(gotActivities, a.ActivityName()+":"+a.Platform)
case fleet.ActivityTypeDisabledManagedLocalAccount:
gotActivities = append(gotActivities, a.ActivityName()+":"+a.Platform)
}
return nil
}
@@ -3118,15 +3185,12 @@ func TestModifyAppConfigManagedLocalAccount(t *testing.T) {
require.Error(t, err)
require.Contains(t, err.Error(), tt.wantErr)
require.Empty(t, gotActivities)
require.False(t, ds.SaveAppConfigFuncInvoked, "config should not have been saved")
return
}
require.NoError(t, err)
var wantActivities []string
if tt.wantActivity != "" {
wantActivities = []string{tt.wantActivity}
}
require.Equal(t, wantActivities, gotActivities)
require.Equal(t, tt.wantActivities, gotActivities)
require.Equal(t, tt.wantWindowsEnabled, dsAppConfig.MDM.WindowsSettings.ManagedLocalAccountSettings.Enabled.Value)
})
}
}
+15 -15
View File
@@ -218,6 +218,16 @@ func (s *integrationEnterpriseTestSuite) clearOktaConditionalAccess() {
s.DoRaw("PATCH", "/api/latest/fleet/config", b, http.StatusOK)
}
// defaultExpectedWindowsSettings returns the WindowsSettings shape produced by a team config
// save/load round trip with nothing configured: an empty custom settings slice and the managed
// local account toggle force-defaulted to disabled.
func defaultExpectedWindowsSettings() fleet.WindowsSettings {
return fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
ManagedLocalAccountSettings: fleet.ManagedLocalAccountSettings{Enabled: optjson.SetBool(false)},
}
}
func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
t := s.T()
@@ -340,9 +350,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
// because the WindowsSettings was marshalled to JSON to be saved in the DB,
// it did get marshalled, and then when unmarshalled it was set (but
// empty).
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
},
WindowsSettings: defaultExpectedWindowsSettings(),
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
Certificates: optjson.Slice[fleet.CertificateTemplateSpec]{Set: true, Value: []fleet.CertificateTemplateSpec{}},
@@ -469,9 +477,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
EnableManagedLocalAccount: optjson.SetBool(false),
EndUserLocalAccountType: optjson.SetString("admin"),
},
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
},
WindowsSettings: defaultExpectedWindowsSettings(),
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
Certificates: optjson.Slice[fleet.CertificateTemplateSpec]{Set: true, Value: []fleet.CertificateTemplateSpec{}},
@@ -512,9 +518,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
EnableManagedLocalAccount: optjson.SetBool(false),
EndUserLocalAccountType: optjson.SetString("admin"),
},
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
},
WindowsSettings: defaultExpectedWindowsSettings(),
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
Certificates: optjson.Slice[fleet.CertificateTemplateSpec]{Set: true, Value: []fleet.CertificateTemplateSpec{}},
@@ -557,9 +561,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
EnableManagedLocalAccount: optjson.SetBool(false),
EndUserLocalAccountType: optjson.SetString("admin"),
},
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
},
WindowsSettings: defaultExpectedWindowsSettings(),
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
Certificates: optjson.Slice[fleet.CertificateTemplateSpec]{Set: true, Value: []fleet.CertificateTemplateSpec{}},
@@ -3460,9 +3462,7 @@ func (s *integrationEnterpriseTestSuite) TestWindowsUpdatesTeamConfig() {
EnableManagedLocalAccount: optjson.SetBool(false),
EndUserLocalAccountType: optjson.SetString("admin"),
},
WindowsSettings: fleet.WindowsSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
},
WindowsSettings: defaultExpectedWindowsSettings(),
AndroidSettings: fleet.AndroidSettings{
CustomSettings: optjson.Slice[fleet.MDMProfileSpec]{Set: true, Value: []fleet.MDMProfileSpec{}},
Certificates: optjson.Slice[fleet.CertificateTemplateSpec]{Set: true, Value: []fleet.CertificateTemplateSpec{}},
+6 -6
View File
@@ -24657,7 +24657,7 @@ func (s *integrationMDMTestSuite) TestManagedLocalAccount() {
s.Do("PATCH", "/api/latest/fleet/setup_experience",
fleet.MDMAppleSetupPayload{TeamID: &team.ID, EnableManagedLocalAccount: new(true)}, http.StatusNoContent)
s.lastActivityOfTypeMatches(fleet.ActivityTypeEnabledManagedLocalAccount{}.ActivityName(),
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q}`, team.ID, team.Name, team.ID, team.Name), 0)
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "platform": "darwin"}`, team.ID, team.Name, team.ID, team.Name), 0)
// Assign ABM org to the team
var acResp appConfigResponse
@@ -24854,7 +24854,7 @@ func (s *integrationMDMTestSuite) TestManagedLocalAccount() {
s.Do("PATCH", "/api/latest/fleet/setup_experience",
fleet.MDMAppleSetupPayload{TeamID: &team.ID, EnableManagedLocalAccount: new(false)}, http.StatusNoContent)
s.lastActivityOfTypeMatches(fleet.ActivityTypeDisabledManagedLocalAccount{}.ActivityName(),
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q}`, team.ID, team.Name, team.ID, team.Name), 0)
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "platform": "darwin"}`, team.ID, team.Name, team.ID, team.Name), 0)
// Existing host's password is still readable
pwdResp = getHostManagedAccountPasswordResponse{}
@@ -24939,7 +24939,7 @@ func (s *integrationMDMTestSuite) TestManagedLocalAccount() {
require.True(t, acResp.MDM.MacOSSetup.EnableManagedLocalAccount.Valid)
require.True(t, acResp.MDM.MacOSSetup.EnableManagedLocalAccount.Value)
lastActivityID := s.lastActivityOfTypeMatches(fleet.ActivityTypeEnabledManagedLocalAccount{}.ActivityName(),
`{"team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
`{"team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null, "platform": "darwin"}`, 0)
// Patching same value again should not create a new activity
s.Do("PATCH", "/api/latest/fleet/setup_experience",
@@ -24956,7 +24956,7 @@ func (s *integrationMDMTestSuite) TestManagedLocalAccount() {
require.True(t, acResp.MDM.MacOSSetup.EnableManagedLocalAccount.Valid)
require.False(t, acResp.MDM.MacOSSetup.EnableManagedLocalAccount.Value)
require.Greater(t, s.lastActivityOfTypeMatches(fleet.ActivityTypeDisabledManagedLocalAccount{}.ActivityName(),
`{"team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0), lastActivityID)
`{"team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null, "platform": "darwin"}`, 0), lastActivityID)
})
t.Run("Rotation flow", func(t *testing.T) {
@@ -25212,7 +25212,7 @@ func (s *integrationMDMTestSuite) TestManagedLocalAccount() {
s.DoJSON("POST", "/api/latest/fleet/teams", &fleet.Team{Name: t.Name() + "team"}, http.StatusOK, &createTeamResp)
tm := createTeamResp.Team
tmConfigPath := fmt.Sprintf("/api/latest/fleet/teams/%d", tm.ID)
expectedDetail := fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q}`, tm.ID, tm.Name, tm.ID, tm.Name)
expectedDetail := fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "platform": "darwin"}`, tm.ID, tm.Name, tm.ID, tm.Name)
// Enable via PATCH /setup_experience
s.Do("PATCH", "/api/latest/fleet/setup_experience",
@@ -25249,7 +25249,7 @@ func (s *integrationMDMTestSuite) TestManagedLocalAccount() {
s.DoJSON("POST", "/api/latest/fleet/teams", &fleet.Team{Name: t.Name() + "team"}, http.StatusOK, &createTeamResp)
tm := createTeamResp.Team
tmConfigPath := fmt.Sprintf("/api/latest/fleet/teams/%d", tm.ID)
expectedDetail := fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q}`, tm.ID, tm.Name, tm.ID, tm.Name)
expectedDetail := fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "platform": "darwin"}`, tm.ID, tm.Name, tm.ID, tm.Name)
// Enable via PATCH /teams/:id
var tmResp teamResponse