Skip to content

UI: Allow conditional access bypass per-policy - #39667

Merged
jacobshandling merged 12 commits into
mainfrom
39000-allow-ca-bypass-per-policy
Feb 12, 2026
Merged

UI: Allow conditional access bypass per-policy#39667
jacobshandling merged 12 commits into
mainfrom
39000-allow-ca-bypass-per-policy

Conversation

@jacobshandling

@jacobshandling jacobshandling commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Related issue: Resolves #39000

Screenshot 2026-02-10 at 8 44 22 PM
  • Changes file added for user-visible changes in `changes/
  • Added/updated automated tests
  • QA'd all new/changed functionality manually - TODO with wip API portion

Summary by CodeRabbit

  • New Features
    • Fleet administrators can now control conditional access bypass on a per-policy basis
    • Added toggles to enable or disable bypass for individual policies
    • Enhanced UI with tooltips displaying conditional access provider configuration details

@jacobshandling

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@codecov

codecov Bot commented Feb 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 20.00000% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.21%. Comparing base (5998ba0) to head (651aa41).
⚠️ Report is 37 commits behind head on main.

Files with missing lines Patch % Lines
.../ConditionalAccessModal/ConditionalAccessModal.tsx 0.00% 14 Missing ⚠️
...es/hosts/details/DeviceUserPage/DeviceUserPage.tsx 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #39667      +/-   ##
==========================================
- Coverage   66.21%   66.21%   -0.01%     
==========================================
  Files        2436     2436              
  Lines      194968   194982      +14     
  Branches     8594     8600       +6     
==========================================
  Hits       129100   129100              
- Misses      54157    54171      +14     
  Partials    11711    11711              
Flag Coverage Δ
frontend 54.21% <20.00%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR implements the frontend UI for per-policy conditional access bypass configuration. It adds a new conditional_access_bypass_enabled field to policy interfaces and mock data. The ConditionalAccess card now displays provider details via tooltips. A new conditional access modal includes per-policy checkbox controls for eligible policies (macOS, Okta-configured, bypass not disabled). The DeviceUserPage gates the bypass resolution action based on both global feature flag and the specific policy's bypass setting. API payloads for policy updates now include the new field.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements the two completed UI objectives from issue #39000 (Integrations > Conditional access and My device > Policy resolution modal) but leaves the primary objective incomplete: the Conditional Access modal checkbox list remains unchecked in the linked issue. The Policies > automations > Conditional access modal checkbox in issue #39000 must be marked complete. Verify all UI elements from the Figma design are fully implemented before merging.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature: allowing conditional access bypass configuration on a per-policy basis in the UI, matching the changeset's primary objective.
Description check ✅ Passed The description includes a related issue reference (#39000), mentions a changes file addition, documents that tests were added, and explicitly notes a TODO for manual QA pending the API portion. However, several checklist items are not checked or addressed.
Out of Scope Changes check ✅ Passed All changes are scoped to UI updates for per-policy conditional access bypass configuration: interface updates, mock data, tests, and component modifications align with issue #39000 objectives. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 39000-allow-ca-bypass-per-policy

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/pages/policies/ManagePoliciesPage/ManagePoliciesPage.tsx (1)

777-788: ⚠️ Potential issue | 🔴 Critical

Bug: responses.concat(...) doesn't mutate responses — policy updates are never awaited.

Array.prototype.concat returns a new array; it does not modify responses in place. The promises from the changedPolicies.map(...) call are silently discarded, so Promise.all(responses) on Line 788 never awaits the policy updates. This means:

  • The success flash may appear before policies are actually saved.
  • Errors from policy updates are silently swallowed.

Note: the same pre-existing bug exists at Line 710 in onUpdateCalendarEvents.

🐛 Proposed fix
-      responses.concat(
-        changedPolicies.map((changedPolicy) => {
+      responses.push(
+        ...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,
           });
         })
       );

And for the pre-existing calendar events bug at Line 710:

-      responses.concat(
-        formData.changedPolicies.map((changedPolicy) => {
+      responses.push(
+        ...formData.changedPolicies.map((changedPolicy) => {
           return teamPoliciesAPI.update(changedPolicy.id, {
             calendar_events_enabled: changedPolicy.calendar_events_enabled,
             team_id: teamIdForApi,
           });
         })
       );
frontend/pages/admin/IntegrationsPage/cards/ConditionalAccess/ConditionalAccess.tsx (1)

348-376: ⚠️ Potential issue | 🟠 Major

Add microsoft_entra_connection_configured to the update payload in handleSaveBypassSettings.

The Okta deletion handler (visible in the search results) explicitly includes both microsoft_entra_tenant_id and microsoft_entra_connection_configured when updating the config. However, handleSaveBypassSettings only includes microsoft_entra_tenant_id and omits microsoft_entra_connection_configured.

Since the backend saves the entire ConditionalAccessSettings object as JSON and microsoft_entra_connection_configured is a plain bool field (not using optjson for partial updates), omitting it will cause it to be reset to false during the update, inadvertently breaking an active Microsoft Entra integration.

To match the pattern in the delete handler and preserve the Entra connection state, add:

microsoft_entra_connection_configured:
  config?.conditional_access?.microsoft_entra_connection_configured || false,
🤖 Fix all issues with AI agents
In
`@frontend/pages/admin/IntegrationsPage/cards/ConditionalAccess/ConditionalAccess.tsx`:
- Around line 465-479: In ConditionalAccess.tsx fix two minor UI text issues:
inside the TooltipWrapper for Microsoft Entra ensure there is a space between
the closing <b> tag and the entraTenantId expression so the tooltip renders
"Tenant ID: {entraTenantId}" with a space, and make the trailing sentence
consistent by adding a period to the Entra status text so the phrase rendered by
the entraContent JSX ("Microsoft Entra ... conditional access connected.")
matches the Okta variant; locate the TooltipWrapper and the entraContent JSX to
apply these changes.

In
`@frontend/pages/policies/ManagePoliciesPage/components/ConditionalAccessModal/ConditionalAccessModal.tsx`:
- Around line 85-121: renderItemRow currently always renders a clickable
span/Checkbox even when the parent list is disabled via
disableList={!formData.enabled}; update renderItemRow to accept or read the
disabled state (from the prop passed to PoliciesPaginatedList or
formData.enabled) and early-return null when disabled OR render a
non-interactive Checkbox by setting its disabled prop and removing/guarding the
span onClick stopPropagation so it cannot be clicked; update the call site where
renderItemRow is passed to PoliciesPaginatedList to pass the disabled flag
through (or reference formData.enabled inside renderItemRow) and ensure the
Checkbox uses conditional prop conditional_access_bypass_enabled only for
display when disabled.
🧹 Nitpick comments (1)
frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx (1)

609-627: Missing test for conditional_access_bypass_enabled: false.

There's a test verifying the button is hidden when conditional_access_enabled is false, but no equivalent test when conditional_access_bypass_enabled is false. Since DeviceUserPage.tsx now gates on both fields, consider adding a test to verify Resolve later is hidden when a policy has conditional_access_bypass_enabled: false.

@getvictor getvictor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jacobshandling
jacobshandling merged commit 97ad0c5 into main Feb 12, 2026
17 checks passed
@jacobshandling
jacobshandling deleted the 39000-allow-ca-bypass-per-policy branch February 12, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Okta conditional access, specify bypass option by policy: UI

2 participants