Remove Windows MDM feature flag (#15167)

For #14959 

---------

Co-authored-by: Gabriel Hernandez <ghernandez345@gmail.com>
This commit is contained in:
Martin Angers 2023-12-07 12:24:32 -05:00 committed by GitHub
parent f4e7789e35
commit 8b7d1a7e47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 35 additions and 187 deletions

View File

@ -0,0 +1,2 @@
* Removed the `FLEET_DEV_MDM_ENABLED` feature flag that allowed enabling Windows MDM. The feature flag is not used anymore, and Windows MDM can be enabled without it.

View File

@ -553,8 +553,8 @@ the way that the Fleet server works.
wstepCertManager microsoft_mdm.CertManager
)
// Configuring WSTEP certs if Windows MDM feature flag is enabled
if configpkg.IsMDMFeatureFlagEnabled() && config.MDM.IsMicrosoftWSTEPSet() {
// Configuring WSTEP certs
if config.MDM.IsMicrosoftWSTEPSet() {
_, crtPEM, keyPEM, err := config.MDM.MicrosoftWSTEP()
if err != nil {
initFatal(err, "validate Microsoft WSTEP certificate and key")

View File

@ -14,7 +14,6 @@ import (
"path/filepath"
"sort"
"strconv"
"strings"
"sync"
"testing"
"time"
@ -902,8 +901,6 @@ func mobileconfigForTest(name, identifier string) []byte {
}
func TestApplyAsGitOps(t *testing.T) {
t.Setenv("FLEET_DEV_MDM_ENABLED", "1")
enqueuer := new(nanomdm_mock.Storage)
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
@ -3338,17 +3335,6 @@ spec:
`, macSetupFile),
wantErr: `macOS MDM isn't turned on.`,
},
{
desc: "app config enable windows mdm without feature flag",
spec: `
apiVersion: v1
kind: config
spec:
mdm:
windows_enabled_and_configured: true
`,
wantErr: `422 Validation Failed: cannot enable Windows MDM without the feature flag explicitly enabled`,
},
{
desc: "app config enable windows mdm without WSTEP",
spec: `
@ -3370,12 +3356,6 @@ spec:
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
for _, c := range cases {
t.Run(c.desc, func(t *testing.T) {
// bit hacky, but since the env var is temporary while Windows MDM is in beta,
// didn't want to add a field to the test cases just for this.
if strings.Contains(c.desc, "WSTEP") {
t.Setenv("FLEET_DEV_MDM_ENABLED", "1")
}
_, ds := runServerWithMockedDS(t, &service.TestServerOpts{License: license})
setupDS(ds)
filename := writeTmpYml(t, c.spec)

View File

@ -207,10 +207,6 @@ export interface IConfig {
};
};
mdm: IMdmConfig;
/** This is the flag that determines if the windwos mdm feature flag is enabled.
TODO: WINDOWS FEATURE FLAG: remove when windows MDM is released. Only used for windows MDM dev currently.
*/
mdm_enabled?: boolean;
}
export interface IWebhookSettings {

View File

@ -106,11 +106,7 @@ const DiskEncryption = ({
return "If turned on, hosts' disk encryption keys will be stored in Fleet. ";
}
const isWindowsFeatureFlagEnabled = config?.mdm_enabled ?? false;
const dynamicText = isWindowsFeatureFlagEnabled
? " and “BitLocker” on Windows"
: "";
return `Also known as “FileVault” on macOS${dynamicText}. If turned on, hosts' disk encryption keys will be stored in Fleet. `;
return `Also known as “FileVault” on macOS and “BitLocker” on Windows. If turned on, hosts' disk encryption keys will be stored in Fleet. `;
};
return (

View File

@ -20,8 +20,6 @@ interface IDiskEncryptionTableProps {
}
const DiskEncryptionTable = ({ currentTeamId }: IDiskEncryptionTableProps) => {
const { config } = useContext(AppContext);
const {
data: diskEncryptionStatusData,
error: diskEncryptionStatusError,
@ -34,15 +32,8 @@ const DiskEncryptionTable = ({ currentTeamId }: IDiskEncryptionTableProps) => {
}
);
// TODO: WINDOWS FEATURE FLAG: remove this when windows feature flag is removed.
// this is used to conditianlly show "View all hosts" link in table cells.
const windowsFeatureFlagEnabled = config?.mdm_enabled ?? false;
const tableHeaders = generateTableHeaders(windowsFeatureFlagEnabled);
const tableData = generateTableData(
windowsFeatureFlagEnabled,
diskEncryptionStatusData,
currentTeamId
);
const tableHeaders = generateTableHeaders();
const tableData = generateTableData(diskEncryptionStatusData, currentTeamId);
if (diskEncryptionStatusError) {
return <DataError />;

View File

@ -32,7 +32,6 @@ interface ICellProps {
};
row: {
original: {
includeWindows: boolean;
status: IStatusCellValue;
teamId: number;
};
@ -94,10 +93,6 @@ const defaultTableHeaders: IDataColumn[] = [
return (
<div className="disk-encryption-table__aggregate-table-data">
<TextCell value={aggregateCount} formatter={(val) => <>{val}</>} />
{/* TODO: WINDOWS FEATURE FLAG: remove this conditional when windows mdm
is released. the view all UI will show in the windows column when we
release the feature. */}
{!original.includeWindows && (
<ViewAllHostsLink
className="view-hosts-link"
queryParams={{
@ -105,7 +100,6 @@ const defaultTableHeaders: IDataColumn[] = [
team_id: original.teamId,
}}
/>
)}
</div>
);
},
@ -144,14 +138,8 @@ const windowsTableHeader: IDataColumn[] = [
},
];
// TODO: WINDOWS FEATURE FLAG: return all headers when windows feature flag is removed.
export const generateTableHeaders = (
includeWindows: boolean
): IDataColumn[] => {
return includeWindows
? [...defaultTableHeaders, ...windowsTableHeader]
: defaultTableHeaders;
return defaultTableHeaders;
export const generateTableHeaders = (): IDataColumn[] => {
return [...defaultTableHeaders, ...windowsTableHeader];
};
const STATUS_CELL_VALUES: Record<DiskEncryptionStatus, IStatusCellValue> = {
@ -215,9 +203,6 @@ const STATUS_ORDER = [
] as const;
export const generateTableData = (
// TODO: WINDOWS FEATURE FLAG: remove includeWindows when windows feature flag is removed.
// This is used to conditionally show "View all hosts" link in table cells.
includeWindows: boolean,
data?: IDiskEncryptionSummaryResponse,
currentTeamId?: number
) => {
@ -227,7 +212,6 @@ export const generateTableData = (
status: DiskEncryptionStatus,
statusAggregate: IDiskEncryptionStatusAggregate
) => ({
includeWindows,
status: STATUS_CELL_VALUES[status],
macosHosts: statusAggregate.macos,
windowsHosts: statusAggregate.windows,

View File

@ -234,11 +234,9 @@ const AppleBusinessManagerSection = ({
<div className={baseClass}>
<h2>Apple Business Manager</h2>
{isLoadingMdmAppleBm ? <Spinner /> : renderAppleBMInfo()}
{config?.mdm_enabled && (
<WindowsAutomaticEnrollmentCard
viewDetails={navigateToWindowsAutomaticEnrollment}
/>
)}
{showEditTeamModal && (
<EditTeamModal
onCancel={toggleEditTeamModal}

View File

@ -63,13 +63,10 @@ const MdmSettings = ({ router }: IMdmSettingsProps) => {
turnOnMacOSMdm={navigateToMacOSMdm}
viewDetails={navigateToMacOSMdm}
/>
{/* TODO: remove conditional rendering when windows MDM is released. */}
{config?.mdm_enabled && (
<WindowsMdmCard
turnOnWindowsMdm={navigateToWindowsMdm}
editWindowsMdm={navigateToWindowsMdm}
/>
)}
</>
)}
</div>

View File

@ -111,12 +111,6 @@ interface IWindowsMdmPageProps {
const WindowsMdmPage = ({ router }: IWindowsMdmPageProps) => {
const { config } = useContext(AppContext);
// TODO: remove when windows MDM is fully released. This is a temporary redirect
// when the feature is not enabled.
if (!config?.mdm_enabled) {
router.replace(PATHS.ADMIN_INTEGRATIONS_MDM);
}
const isWindowsMdmEnabled =
config?.mdm?.windows_enabled_and_configured ?? false;

View File

@ -1741,13 +1741,3 @@ func SetTestMDMConfig(t testing.TB, cfg *FleetConfig, cert, key []byte, appleBMT
t.Fatal(err)
}
}
// Undocumented feature flag for Windows MDM, used to determine if the Windows
// MDM feature is visible in the UI and can be enabled. More details here:
// https://github.com/fleetdm/fleet/issues/12257
//
// TODO: remove this flag once the Windows MDM feature is ready for
// release.
func IsMDMFeatureFlagEnabled() bool {
return os.Getenv("FLEET_DEV_MDM_ENABLED") == "1"
}

View File

@ -174,10 +174,7 @@ type MDM struct {
// AtLeastOnePlatformEnabledAndConfigured returns true if at least one supported platform
// (macOS or Windows) has MDM enabled and configured.
func (m MDM) AtLeastOnePlatformEnabledAndConfigured() bool {
// explicitly check for the feature flag to account for the edge case of:
// 1. FF enabled, windows is turned on
// 2. FF disabled on server restart
return m.EnabledAndConfigured || (config.IsMDMFeatureFlagEnabled() && m.WindowsEnabledAndConfigured)
return m.EnabledAndConfigured || m.WindowsEnabledAndConfigured
}
// versionStringRegex is used to validate that a version string is in the x.y.z

View File

@ -315,75 +315,36 @@ func TestAtLeastOnePlatformEnabledAndConfigured(t *testing.T) {
name string
macOSEnabledAndConfigured bool
windowsEnabledAndConfigured bool
isMDMFeatureFlagEnabled bool
expectedResult bool
}{
{
name: "None enabled, feature flag disabled",
name: "None enabled",
macOSEnabledAndConfigured: false,
windowsEnabledAndConfigured: false,
isMDMFeatureFlagEnabled: false,
expectedResult: false,
},
{
name: "MacOS enabled, feature flag disabled",
name: "MacOS enabled",
macOSEnabledAndConfigured: true,
windowsEnabledAndConfigured: false,
isMDMFeatureFlagEnabled: false,
expectedResult: true,
},
{
name: "Windows enabled, feature flag disabled",
macOSEnabledAndConfigured: false,
windowsEnabledAndConfigured: true,
isMDMFeatureFlagEnabled: false,
expectedResult: false,
},
{
name: "Both enabled, feature flag disabled",
name: "Both enabled",
macOSEnabledAndConfigured: true,
windowsEnabledAndConfigured: true,
isMDMFeatureFlagEnabled: false,
expectedResult: true,
},
{
name: "None enabled, feature flag enabled",
macOSEnabledAndConfigured: false,
windowsEnabledAndConfigured: false,
isMDMFeatureFlagEnabled: true,
expectedResult: false,
},
{
name: "MacOS enabled, feature flag enabled",
macOSEnabledAndConfigured: true,
windowsEnabledAndConfigured: false,
isMDMFeatureFlagEnabled: true,
expectedResult: true,
},
{
name: "Windows enabled, feature flag enabled",
name: "Windows enabled",
macOSEnabledAndConfigured: false,
windowsEnabledAndConfigured: true,
isMDMFeatureFlagEnabled: true,
expectedResult: true,
},
{
name: "Both enabled, feature flag enabled",
macOSEnabledAndConfigured: true,
windowsEnabledAndConfigured: true,
isMDMFeatureFlagEnabled: true,
expectedResult: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if test.isMDMFeatureFlagEnabled {
t.Setenv("FLEET_DEV_MDM_ENABLED", "1")
} else {
t.Setenv("FLEET_DEV_MDM_ENABLED", "0")
}
mdm := MDM{
EnabledAndConfigured: test.macOSEnabledAndConfigured,
WindowsEnabledAndConfigured: test.windowsEnabledAndConfigured,

View File

@ -17,7 +17,6 @@ import (
"github.com/fleetdm/fleet/v4/pkg/rawjson"
"github.com/fleetdm/fleet/v4/server"
"github.com/fleetdm/fleet/v4/server/authz"
"github.com/fleetdm/fleet/v4/server/config"
authz_ctx "github.com/fleetdm/fleet/v4/server/contexts/authz"
"github.com/fleetdm/fleet/v4/server/contexts/ctxdb"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
@ -51,17 +50,6 @@ type appConfigResponseFields struct {
// SandboxEnabled is true if fleet serve was ran with server.sandbox_enabled=true
SandboxEnabled bool `json:"sandbox_enabled,omitempty"`
Err error `json:"error,omitempty"`
// MDMEnabled is true if fleet serve was started with
// FLEET_DEV_MDM_ENABLED=1.
//
// Undocumented feature flag for Windows MDM, used to determine if the
// Windows MDM feature is visible in the UI and can be enabled. More details
// here: https://github.com/fleetdm/fleet/issues/12257
//
// TODO: remove this flag once the Windows MDM feature is ready for
// release.
MDMEnabled bool `json:"mdm_enabled,omitempty"`
}
// UnmarshalJSON implements the json.Unmarshaler interface to make sure we serialize
@ -186,7 +174,6 @@ func getAppConfigEndpoint(ctx context.Context, request interface{}, svc fleet.Se
Logging: loggingConfig,
Email: emailConfig,
SandboxEnabled: svc.SandboxEnabled(),
MDMEnabled: config.IsMDMFeatureFlagEnabled(),
},
}
return response, nil
@ -245,7 +232,6 @@ func modifyAppConfigEndpoint(ctx context.Context, request interface{}, svc fleet
appConfigResponseFields: appConfigResponseFields{
License: license,
Logging: loggingConfig,
MDMEnabled: config.IsMDMFeatureFlagEnabled(),
},
}
@ -786,12 +772,6 @@ func (svc *Service) validateMDM(
}
// Windows validation
if !config.IsMDMFeatureFlagEnabled() {
if mdm.WindowsEnabledAndConfigured {
invalid.Append("mdm.windows_enabled_and_configured", "cannot enable Windows MDM without the feature flag explicitly enabled")
return
}
}
if !svc.config.MDM.IsMicrosoftWSTEPSet() {
if mdm.WindowsEnabledAndConfigured {
invalid.Append("mdm.windows_enabled_and_configured", "Couldn't turn on Windows MDM. Please configure Fleet with a certificate and key pair first.")

View File

@ -5222,7 +5222,6 @@ func (s *integrationTestSuite) TestAppConfig() {
assert.Equal(t, "free", acResp.License.Tier)
assert.Equal(t, "FleetTest", acResp.OrgInfo.OrgName) // set in SetupSuite
assert.False(t, acResp.MDM.AppleBMTermsExpired)
assert.False(t, acResp.MDMEnabled)
// set the apple BM terms expired flag, and the enabled and configured flags,
// we'll check again at the end of this test to make sure they weren't
@ -5251,7 +5250,6 @@ func (s *integrationTestSuite) TestAppConfig() {
}`), http.StatusOK, &acResp)
assert.Equal(t, "test", acResp.OrgInfo.OrgName)
assert.True(t, acResp.MDM.AppleBMTermsExpired)
assert.False(t, acResp.MDMEnabled)
// the global agent options were not modified by the last call, so the
// corresponding activity should not have been created.
@ -5450,13 +5448,13 @@ func (s *integrationTestSuite) TestAppConfig() {
errMsg = extractServerErrorText(res.Body)
assert.Contains(t, errMsg, "missing or invalid license")
// try to enable Windows MDM, impossible without the feature flag
// try to enable Windows MDM, impossible without the WSTEP certs
// (only set in mdm integrations tests)
res = s.Do("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
"mdm": { "windows_enabled_and_configured": true }
}`), http.StatusUnprocessableEntity)
errMsg = extractServerErrorText(res.Body)
assert.Contains(t, errMsg, "cannot enable Windows MDM without the feature flag explicitly enabled")
assert.Contains(t, errMsg, "Please configure Fleet with a certificate and key pair first.")
// verify that the Apple BM terms expired flag was never modified
acResp = appConfigResponse{}

View File

@ -64,8 +64,6 @@ import (
)
func TestIntegrationsMDM(t *testing.T) {
t.Setenv("FLEET_DEV_MDM_ENABLED", "1")
testingSuite := new(integrationMDMTestSuite)
testingSuite.s = &testingSuite.Suite
suite.Run(t, testingSuite)
@ -2796,16 +2794,9 @@ func (s *integrationMDMTestSuite) TestDiskEncryptionSharedSetting() {
s.Do("POST", "/api/latest/fleet/spec/teams", teamSpecs, http.StatusOK)
}
// 1. disable both windows and mac mdm
// 2. turn off windows feature flag
// disable both windows and mac mdm
// we should get an error
setMDMEnabled(false, false)
t.Setenv("FLEET_DEV_MDM_ENABLED", "0")
checkConfigSetErrors()
// turn on windows feature flag
// we should get an error
t.Setenv("FLEET_DEV_MDM_ENABLED", "1")
checkConfigSetErrors()
// enable windows mdm, no errors
@ -6965,7 +6956,6 @@ func (s *integrationMDMTestSuite) TestAppConfigWindowsMDM() {
// the feature flag is enabled for the MDM test suite
var acResp appConfigResponse
s.DoJSON("GET", "/api/latest/fleet/config", nil, http.StatusOK, &acResp)
assert.True(t, acResp.MDMEnabled)
assert.False(t, acResp.MDM.WindowsEnabledAndConfigured)
// create a couple teams
@ -7013,7 +7003,6 @@ func (s *integrationMDMTestSuite) TestAppConfigWindowsMDM() {
"mdm": { "windows_enabled_and_configured": true }
}`), http.StatusOK, &acResp)
assert.True(t, acResp.MDM.WindowsEnabledAndConfigured)
assert.True(t, acResp.MDMEnabled)
s.lastActivityOfTypeMatches(fleet.ActivityTypeEnabledWindowsMDM{}.ActivityName(), `{}`, 0)
// get the orbit config for each host, verify that only the expected ones

View File

@ -8,7 +8,6 @@ import (
"time"
"github.com/fleetdm/fleet/v4/server"
"github.com/fleetdm/fleet/v4/server/config"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
hostctx "github.com/fleetdm/fleet/v4/server/contexts/host"
"github.com/fleetdm/fleet/v4/server/contexts/license"
@ -218,7 +217,7 @@ func (svc *Service) GetOrbitConfig(ctx context.Context) (fleet.OrbitConfig, erro
notifs.NeedsProgrammaticWindowsMDMEnrollment = true
}
}
if config.IsMDMFeatureFlagEnabled() && !appConfig.MDM.WindowsEnabledAndConfigured {
if !appConfig.MDM.WindowsEnabledAndConfigured {
if host.IsEligibleForWindowsMDMUnenrollment() {
notifs.NeedsProgrammaticWindowsMDMUnenrollment = true
}
@ -271,8 +270,7 @@ func (svc *Service) GetOrbitConfig(ctx context.Context) (fleet.OrbitConfig, erro
}
}
if config.IsMDMFeatureFlagEnabled() &&
mdmConfig.EnableDiskEncryption &&
if mdmConfig.EnableDiskEncryption &&
host.IsEligibleForBitLockerEncryption() {
notifs.EnforceBitLockerEncryption = true
}
@ -308,7 +306,6 @@ func (svc *Service) GetOrbitConfig(ctx context.Context) (fleet.OrbitConfig, erro
}
if appConfig.MDM.WindowsEnabledAndConfigured &&
config.IsMDMFeatureFlagEnabled() &&
appConfig.MDM.EnableDiskEncryption.Value &&
host.IsEligibleForBitLockerEncryption() {
notifs.EnforceBitLockerEncryption = true

View File

@ -1,8 +1,6 @@
output "extra_environment_variables" {
value = merge(var.enable_apple_mdm == false ? {} : {
FLEET_MDM_APPLE_SERVER_ADDRESS = var.public_domain_name
}, var.enable_windows_mdm == false ? {} : {
FLEET_DEV_MDM_ENABLED = "1"
})
}