UI: Remove experimental conditional_access_bypass_enabled policy setting in favor of critical (#40924)

**Related issue:** Resolves #40417
<img width="1624" height="1061" alt="Screenshot 2026-03-03 at 4 17
19 PM"
src="https://github.com/user-attachments/assets/feb3f4cd-af20-42be-887a-73ccef4f2b23"
/>
<img width="1624" height="1061" alt="Screenshot 2026-03-03 at 4 19
17 PM"
src="https://github.com/user-attachments/assets/0b67e5df-525f-444d-8521-f1de1527cfaa"
/>
<img width="1624" height="1061" alt="Screenshot 2026-03-03 at 4 19
26 PM"
src="https://github.com/user-attachments/assets/922f6f05-4889-430f-9da9-3f8f0ac5a11c"
/>
<img width="1624" height="1061" alt="Screenshot 2026-03-03 at 4 19
45 PM"
src="https://github.com/user-attachments/assets/65445602-8a83-429f-aaaf-729f127c4c4b"
/>

- [x] Changes file added for user-visible changes in `changes/`
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

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

## Summary by CodeRabbit

## Release Notes

* **New Features**
  * Added visual badge to identify critical policies.

* **Improvements**
* Critical policies can no longer be bypassed when Okta conditional
access is configured.
* Simplified conditional access policy management UI by removing
per-policy bypass toggles.
* Updated tooltips to clarify bypass restrictions for critical policies.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
jacobshandling
2026-03-04 15:16:13 -08:00
committed by GitHub
parent b7abab942c
commit e9bebfdf96
16 changed files with 64 additions and 124 deletions
-4
View File
@@ -24,7 +24,6 @@ const DEFAULT_POLICY_MOCK: IPolicyStats = {
next_update_ms: 3600000,
calendar_events_enabled: true,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
install_software: {
name: "testSw0",
software_title_id: 1,
@@ -62,7 +61,6 @@ export const createMockPoliciesResponse = (
next_update_ms: 3600000,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
{
id: 29090,
@@ -86,7 +84,6 @@ export const createMockPoliciesResponse = (
next_update_ms: 3600000,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
{
id: 136,
@@ -112,7 +109,6 @@ export const createMockPoliciesResponse = (
next_update_ms: 3600000,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
],
};
@@ -0,0 +1,30 @@
import React from "react";
import Icon from "components/Icon";
import TooltipWrapper from "components/TooltipWrapper";
const baseClass = "critical-badge";
const CriticalPolicyBadge = () => {
return (
<div className={baseClass}>
<TooltipWrapper
tipContent="This policy has been marked as critical."
showArrow
position="top"
tipOffset={8}
underline={false}
fixedPositionStrategy
>
<Icon
className="critical-policy-icon"
name="policy"
size="small"
color="ui-fleet-black-75"
/>
</TooltipWrapper>
</div>
);
};
export default CriticalPolicyBadge;
@@ -0,0 +1 @@
export { default } from "./CriticalPolicyBadge";
+2 -2
View File
@@ -42,10 +42,10 @@ export interface IPolicy {
team_id: number | null;
created_at: string;
updated_at: string;
// A critical policy cannot be "resolved later" if Okta conditional access is enabled for it
critical: boolean;
calendar_events_enabled: boolean;
conditional_access_enabled: boolean;
conditional_access_bypass_enabled: boolean;
install_software?: IPolicySoftwareToInstall;
run_script?: Pick<IScript, "id" | "name">;
labels_include_any?: ILabelPolicy[];
@@ -105,6 +105,7 @@ export interface ILoadTeamPolicyResponse {
export interface IPolicyFormData {
description?: string | number | boolean | undefined;
resolution?: string | number | boolean | undefined;
// A critical policy cannot be "resolved later" if Okta conditional access is enabled for it
critical?: boolean;
platform?: CommaSeparatedPlatformString;
name?: string | number | boolean | undefined;
@@ -113,7 +114,6 @@ export interface IPolicyFormData {
id?: number;
calendar_events_enabled?: boolean;
conditional_access_enabled?: boolean;
conditional_access_bypass_enabled?: boolean;
software_title_id?: number | null;
// null for PATCH to unset - note asymmetry with GET/LIST - see IPolicy.run_script
script_id?: number | null;
@@ -551,15 +551,15 @@ const ConditionalAccess = () => {
<TooltipWrapper
tipContent={
<>
When enabled, disables the per-policy setting to allow
bypassing Okta conditional access.{" "}
Disables bypassing Okta conditional access for non-critical
policies.{" "}
<em>
(Default: <strong>Off</strong>)
</em>
<br />
<br />
Bypassing is valid for a single login attempt and is tracked
in audit logs.
in audit logs. Critical policies can never be bypassed.
</>
}
showArrow={false}
@@ -556,7 +556,6 @@ describe("Device User Page", () => {
critical: false,
calendar_events_enabled: false,
conditional_access_enabled: true,
conditional_access_bypass_enabled: true,
response: "fail",
});
@@ -673,11 +673,8 @@ const DeviceUserPage = ({
);
}
const hasAnyBypassDisabledFailingCAPolicy = host?.policies.some(
(p) =>
p.response === "fail" &&
p.conditional_access_enabled &&
!p.conditional_access_bypass_enabled
const hasAnyCriticalFailingCAPolicy = host?.policies.some(
(p) => p.response === "fail" && p.conditional_access_enabled && p.critical
);
return (
@@ -847,8 +844,7 @@ const DeviceUserPage = ({
onResolveLater={
globalConfig?.features?.enable_conditional_access &&
globalConfig.features?.enable_conditional_access_bypass &&
!hasAnyBypassDisabledFailingCAPolicy &&
selectedPolicy?.conditional_access_bypass_enabled
!hasAnyCriticalFailingCAPolicy
? () => {
onCancelPolicyDetailsModal();
setShowBypassModal(true);
@@ -789,8 +789,6 @@ const ManagePolicyPage = ({
const policyPromises = changedPolicies.map((changedPolicy) => {
return teamPoliciesAPI.update(changedPolicy.id, {
conditional_access_enabled: changedPolicy.conditional_access_enabled,
conditional_access_bypass_enabled:
changedPolicy.conditional_access_bypass_enabled,
team_id: teamIdForApi,
});
});
@@ -1,18 +1,13 @@
import React, { useContext, useRef, useState } from "react";
import {
FLEET_WEBSITE_URL,
LEARN_MORE_ABOUT_BASE_LINK,
} from "utilities/constants";
import { isOktaConditionalAccessConfigured } from "interfaces/config";
import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants";
import TooltipTruncatedText from "components/TooltipTruncatedText";
import CriticalPolicyBadge from "components/CriticalPolicyBadge";
import CustomLink from "components/CustomLink";
import Modal from "components/Modal";
import Button from "components/buttons/Button";
import Slider from "components/forms/fields/Slider";
import Checkbox from "components/forms/fields/Checkbox";
import TooltipWrapper from "components/TooltipWrapper";
import { AppContext } from "context/app";
import { IPaginatedListHandle } from "components/PaginatedList";
import PoliciesPaginatedList, {
@@ -53,7 +48,7 @@ const ConditionalAccessModal = ({
});
const paginatedListRef = useRef<IPaginatedListHandle<IFormPolicy>>(null);
const { isGlobalAdmin, isTeamAdmin, config } = useContext(AppContext);
const { isGlobalAdmin, isTeamAdmin } = useContext(AppContext);
const isAdmin = isGlobalAdmin || isTeamAdmin;
const onChangeEnabled = () => {
@@ -82,58 +77,12 @@ const ConditionalAccessModal = ({
/>
);
const renderItemRow = (
item: IFormPolicy,
onChange: (item: IFormPolicy) => void
) => {
const shouldShowCheckbox =
item.conditional_access_enabled &&
// currently redundant as only darwin-targeting policies are enabled in this list
item.platform.includes("darwin") &&
isOktaConditionalAccessConfigured(config) &&
!config?.conditional_access?.bypass_disabled;
if (!shouldShowCheckbox) {
return null;
}
return (
<span
onClick={(e) => {
e.stopPropagation();
}}
>
<Checkbox
value={item.conditional_access_bypass_enabled}
onChange={() => {
onChange({
...item,
conditional_access_bypass_enabled: !item.conditional_access_bypass_enabled,
});
}}
>
<TooltipWrapper
tipContent={
<>
Allows end users to bypass conditional access for a single login
if they are unable to resolve the failing policy.
<br />
<br />
<em>
This experimental setting will be removed in Fleet 4.83, and
only non-critical policies will allow bypass. For a seamless
upgrade, please avoid enabling bypass for policies marked
critical.
</em>
</>
}
>
End users can bypass
</TooltipWrapper>
</Checkbox>
</span>
);
};
const renderItemLabel = (policy: IFormPolicy) => (
<>
<TooltipTruncatedText value={policy.name} />
{policy.critical && <CriticalPolicyBadge />}
</>
);
const renderConfigured = () => {
return (
@@ -147,19 +96,13 @@ const ConditionalAccessModal = ({
activeText="Enabled"
disabled={gitOpsModeEnabled || !isAdmin}
/>
<CustomLink
text="Preview end user experience"
newTab
multiline={false}
url={`${FLEET_WEBSITE_URL}/microsoft-compliance-partner/remediate`}
/>
</span>
<PoliciesPaginatedList
ref={paginatedListRef}
isSelected="conditional_access_enabled"
getPolicyDisabled={getPolicyDisabled}
getPolicyTooltipContent={getPolicyTooltipContent}
renderItemRow={renderItemRow}
renderItemLabel={renderItemLabel}
onToggleItem={(item: IFormPolicy) => {
item.conditional_access_enabled = !item.conditional_access_enabled;
return item;
@@ -6,4 +6,7 @@
white-space: nowrap;
}
}
.paginated-list .fleet-checkbox__label {
gap: 0.5rem;
}
}
@@ -45,6 +45,7 @@ interface IPoliciesPaginatedListProps {
item: IFormPolicy,
onChange: (item: IFormPolicy) => void
) => ReactElement | false | null | undefined;
renderItemLabel?: (item: IFormPolicy) => ReactElement | null;
onToggleItem: (item: IFormPolicy) => IFormPolicy;
/** A function defining the conditions under which to disable a policy. */
getPolicyDisabled?: (policy: IFormPolicy) => boolean;
@@ -64,6 +65,7 @@ function PoliciesPaginatedList(
{
isSelected,
renderItemRow,
renderItemLabel,
onToggleItem,
getPolicyDisabled,
getPolicyTooltipContent,
@@ -238,6 +240,7 @@ function PoliciesPaginatedList(
isItemDisabled={getPolicyDisabled}
getItemTooltipContent={getPolicyTooltipContent}
onClickRow={onToggleItem}
renderItemLabel={renderItemLabel}
renderItemRow={renderItemRow}
pageSize={DEFAULT_PAGE_SIZE}
onUpdate={onUpdate}
@@ -8,7 +8,6 @@ import { Tooltip as ReactTooltip5 } from "react-tooltip-5";
import Checkbox from "components/forms/fields/Checkbox";
import HeaderCell from "components/TableContainer/DataTable/HeaderCell";
import LinkCell from "components/TableContainer/DataTable/LinkCell/LinkCell";
import Icon from "components/Icon";
import { IPolicyStats } from "interfaces/policy";
import PATHS from "router/paths";
@@ -16,6 +15,7 @@ import { getPathWithQueryParams } from "utilities/url";
import sortUtils from "utilities/sort";
import { PolicyResponse } from "utilities/constants";
import CriticalPolicyBadge from "components/CriticalPolicyBadge";
import InheritedBadge from "components/InheritedBadge";
import { getConditionalSelectHeaderCheckboxProps } from "components/TableContainer/utilities/config_utils";
import GitOpsModeTooltipWrapper from "components/GitOpsModeTooltipWrapper";
@@ -116,32 +116,7 @@ const generateTableHeaders = (
value={cellProps.cell.value}
suffix={
<>
{isPremiumTier && critical && (
<div className="critical-badge">
<span
className="critical-badge-icon"
data-tooltip-id={`critical-tooltip-${id}`}
>
<Icon
className="critical-policy-icon"
name="policy"
size="small"
color="ui-fleet-black-75"
/>
</span>
<ReactTooltip5
className="critical-tooltip"
disableStyleInjection
place="top"
opacity={1}
id={`critical-tooltip-${id}`}
offset={8}
positionStrategy="fixed"
>
This policy has been marked as critical.
</ReactTooltip5>
</div>
)}
{isPremiumTier && critical && <CriticalPolicyBadge />}
{viewingTeamPolicies && team_id === null && (
<InheritedBadge tooltipContent="This policy runs on all hosts." />
)}
@@ -28,7 +28,6 @@ describe("getInstallSoftwareErrorMessage", () => {
critical: false,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
{
swIdToInstall: 456,
@@ -50,7 +49,6 @@ describe("getInstallSoftwareErrorMessage", () => {
critical: false,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
];
@@ -162,7 +160,6 @@ describe("getRunScriptErrorMessage", () => {
critical: false,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
{
scriptIdToRun: 456,
@@ -184,7 +181,6 @@ describe("getRunScriptErrorMessage", () => {
critical: false,
calendar_events_enabled: false,
conditional_access_enabled: false,
conditional_access_bypass_enabled: true,
},
];
@@ -641,8 +641,9 @@ const PolicyForm = ({
<TooltipWrapper
tipContent={
<p>
If automations are turned on, this
<br /> information is included.
If automations are turned on, this information is included. If
Okta conditional access is configured, end users can never
bypass critical policies.
</p>
}
>
@@ -313,8 +313,9 @@ const SaveNewPolicyModal = ({
<TooltipWrapper
tipContent={
<p>
If automations are turned on, this
<br /> information is included.
If automations are turned on, this information is
included. If Okta conditional access is configured, end
users can never bypass critical policies.
</p>
}
>
@@ -97,7 +97,6 @@ export default {
// automations-related fields
calendar_events_enabled,
conditional_access_enabled,
conditional_access_bypass_enabled,
software_title_id,
script_id,
labels_include_any,
@@ -115,7 +114,6 @@ export default {
critical,
calendar_events_enabled,
conditional_access_enabled,
conditional_access_bypass_enabled,
software_title_id,
script_id,
labels_include_any,