-
Notifications
You must be signed in to change notification settings - Fork 75
Conditional Access Review skill #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Conditional Access Review | ||
|
|
||
| Paste in an export of your Microsoft Entra Conditional Access policies and get | ||
| back a coverage matrix, a gap list, and a conflict/hygiene check, grounded in | ||
| Microsoft's own Conditional Access deployment guidance. | ||
|
|
||
| ## What it checks | ||
|
|
||
| - **Coverage**: is MFA actually enforced (not just report-only) for all users, | ||
| legacy auth blocked, high-risk sign-ins handled, admin roles protected, | ||
| guests included? | ||
| - **Break-glass exclusion**: Microsoft's guidance is that every Conditional | ||
| Access policy should exclude at least one emergency access account. This | ||
| skill treats a missing exclusion as a standalone finding on its own, not just | ||
| a detail of one policy. | ||
| - **Conflicts**: two policies covering the same scope with contradictory | ||
| controls. | ||
| - **Hygiene**: redundant policies, generic names, broad exclusions with no | ||
| stated rationale. | ||
|
|
||
| ## Getting an export | ||
|
|
||
| ``` | ||
| GET https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies | ||
| ``` | ||
|
|
||
| via Graph Explorer or the Microsoft Graph PowerShell SDK | ||
| (`Get-MgIdentityConditionalAccessPolicy`). Strip any bearer token before | ||
| pasting. The policy JSON itself contains no secrets, but an API call copied | ||
| wholesale might. | ||
|
|
||
| ## What it won't do | ||
|
|
||
| It never outputs a script that changes, disables, or deletes a policy. Every | ||
| recommendation is either a policy definition to review with a Conditional | ||
| Access Administrator, or the manual steps to take in the Entra admin center. | ||
| You make the change, not the skill. It also can't see real sign-in logs, risk | ||
| data, or actual group membership: everything is inferred from the exported | ||
| configuration. | ||
|
|
||
| ## Reference | ||
|
|
||
| [Plan a Conditional Access deployment](https://learn.microsoft.com/entra/identity/conditional-access/plan-conditional-access) | ||
| · [Manage emergency access accounts](https://learn.microsoft.com/entra/identity/role-based-access-control/security-emergency-access) | ||
| · [Block legacy authentication](https://learn.microsoft.com/entra/identity/conditional-access/policy-block-legacy-authentication) | ||
|
|
||
| --- | ||
|
|
||
| Skill by Tim Karlsson (╯°□°)╯︵ ┻━┻ Works 60% of the time, every time. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| --- | ||
| name: conditional-access-review | ||
| description: >- | ||
| Use this skill whenever the user shares an exported set of Microsoft Entra | ||
| Conditional Access policies (Graph JSON, PowerShell export, or a pasted | ||
| policy list) and asks for a review, gap analysis, or health check, before | ||
| recommending any change to a Conditional Access policy. | ||
| --- | ||
|
|
||
| Review a Conditional Access policy set from an export and report coverage | ||
| gaps, risky exclusions, conflicts, and configuration health, as | ||
| recommendations only. | ||
|
|
||
| ## Instructions | ||
|
|
||
| 1. Get the export. Accepted: Graph API JSON | ||
| (`GET /identity/conditionalAccess/policies`), a PowerShell/Microsoft Graph | ||
| PowerShell SDK export, or a clearly structured pasted list of policies with | ||
| their conditions and controls. If what's given is missing conditions or | ||
| grant controls, ask for the full export rather than guessing at what a | ||
| policy does. | ||
|
|
||
| 2. State this limit up front: this is a **review of the exported | ||
| configuration**, not a live tenant assessment. It cannot see actual sign-in | ||
| logs, real user/group membership, sign-in risk data, or which policies are | ||
| actually enforcing vs. report-only in practice beyond what the export's | ||
| `state` field says. | ||
|
|
||
| 3. For every policy, resolve `state`: `enabled`, `disabled`, or | ||
| `enabledForReportingButNotEnforced`. Treat report-only and disabled policies | ||
| as providing **zero** enforced coverage. Call this out explicitly wherever | ||
| the user's tenant coverage looks fine only because a report-only policy is | ||
| being counted. | ||
|
|
||
| 4. Build a coverage matrix: which combinations of user population, app or | ||
| resource, and sign-in risk actually have an enforced grant control, and | ||
| which don't. Call out the standard high-value coverage checks by name: | ||
| - MFA required for all users (or all admins, at minimum) on all cloud apps | ||
| - Legacy authentication blocked | ||
| - High-risk sign-ins and high-risk users blocked or forced to secure | ||
| password change | ||
| - Device compliance or hybrid-join required for sensitive apps | ||
| - Admin roles covered by phishing-resistant MFA or Privileged Identity | ||
| Management-gated access | ||
|
|
||
| 5. Check for the following, reporting every hit: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the export contains only policy rules with user and group ID numbers, how will the skill can't truthfully say a group is "large," confirm admins or guests are covered, or claim no emergency account exists, in this case? |
||
| - **Exclusions**: any policy excluding a broad group (e.g. "All Users" minus | ||
| a large security group) without an emergency access account rationale. | ||
| Flag any policy that does *not* exclude a break-glass/emergency access | ||
| account, since Microsoft's guidance is to exclude those accounts from | ||
| every Conditional Access policy. | ||
| - **No emergency access accounts found at all** in any policy's exclusions. | ||
| Flag this as a standalone finding regardless of individual policy design. | ||
| - **Conflicts**: two policies targeting the same scope with contradictory | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If any applicable policy says block, the user is blocked. A block policy and a grant policy should not not produce a "weaker-than-intended result, as the platform resolves it deterministically, citing MS docs: "If there's a policy that is configured with the block grant control, enforcement stops here and the user is blocked" |
||
| grant controls (one blocks, one grants) where evaluation order or an | ||
| "OR" of controls could produce a weaker-than-intended result. | ||
| - **Redundant policies**: multiple enabled policies enforcing the same | ||
| control on the same scope. A maintenance and audit-trail risk even when | ||
| harmless today. | ||
| - **Guest/external user coverage**: whether external users are covered by | ||
| the same or an equivalent baseline as internal users. | ||
| - **Naming**: policies with generic names (`Policy1`, `CA01`) that make the | ||
| tenant harder to audit. | ||
|
|
||
| 6. Report findings by severity (Gap, Conflict, Hygiene), each as one row: | ||
|
|
||
| | Severity | Finding | Affected policies | Recommendation | | ||
| | --- | --- | --- | --- | | ||
| | Gap | No enforced MFA policy covers guest users | none | Add guests to the MFA baseline policy or create a guest-specific policy | | ||
|
|
||
| Close with a short "what's covered well" note. A review that only lists | ||
| problems reads as less trustworthy than one that also confirms what's solid. | ||
|
|
||
| 7. Recommendations are prose and example policy JSON/steps only. Never claim to | ||
| have made a change. | ||
|
|
||
| ## Guardrails | ||
|
|
||
| - Never ask the user to paste credentials, access tokens, or client secrets. | ||
| The Graph export itself contains no secrets. If the user offers to paste an | ||
| API call including a bearer token, tell them to strip it first. | ||
| - Never output a script or instruction whose effect is to change, disable, or | ||
| delete a tenant's Conditional Access policy. Output the *recommended policy | ||
| definition* or the *manual steps a Conditional Access Administrator would | ||
| take*. The user or their admin executes it, not this skill. | ||
| - Always flag missing break-glass account exclusion, even if nothing else in | ||
| the review turns up an issue. | ||
| - Don't speculate about why a policy was configured a certain way. Describe | ||
| what it does, not the intent behind it, unless the user explains the intent. | ||
|
|
||
| ## Tone | ||
|
|
||
| Direct and audit-style: finding, evidence from the export, concrete | ||
| recommendation. No alarmism. A coverage gap is a fact, not a crisis, unless | ||
| it's a genuinely severe one (no MFA baseline at all, no break-glass exclusion | ||
| anywhere). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "name": "Conditional Access Review", | ||
| "description": "Review an exported set of Microsoft Entra Conditional Access policies for coverage gaps, missing break-glass exclusions, policy conflicts, and configuration hygiene. Recommendations only, never a live change.", | ||
| "platforms": ["Copilot Studio", "Cowork"], | ||
| "tags": ["entra", "conditional-access", "identity", "security", "governance", "review"], | ||
| "author": "Tim Karlsson", | ||
| "authorUrl": "https://github.com/Timziito", | ||
| "version": "1.0.0", | ||
| "createdAt": "2026-07-26", | ||
| "updatedAt": "2026-07-26" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if the export has no secrets in it , information is still sensitive, as it maps out which apps are protected and where MFA isn't enforced. Worth treating it as sensitive security config rather than harmless and call this out.