From 2b5cc4206eec3b4af39ef847458db070c074bb04 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:41:58 +0000 Subject: [PATCH 01/20] Initial plan From 8b6b78873af7b3c022db3a7f3d9b87c2cdab59fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:49:29 +0000 Subject: [PATCH 02/20] Add Test-MtCaAuthContextProtectedActionsExist test for Protected Actions Auth Context validation Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- ...st-MtCaAuthContextProtectedActionsExist.md | 41 ++++++ ...t-MtCaAuthContextProtectedActionsExist.ps1 | 136 ++++++++++++++++++ .../Test-ConditionalAccessBaseline.Tests.ps1 | 4 + website/docs/tests/maester/MT.1090.md | 49 +++++++ 4 files changed, 230 insertions(+) create mode 100644 powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md create mode 100644 powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 create mode 100644 website/docs/tests/maester/MT.1090.md diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md new file mode 100644 index 000000000..282e83a58 --- /dev/null +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md @@ -0,0 +1,41 @@ +# Protected Actions Authentication Contexts should have Conditional Access policies + +Protected Actions allow organizations to require step-up authentication for sensitive operations by +assigning Authentication Contexts to those actions. However, if an Authentication Context is not +referenced in any Conditional Access policy, the protected action is not effectively protected. + +This test verifies that all Authentication Contexts used by Protected Actions are properly referenced +in at least one Conditional Access policy. + +## How to fix + +If this test fails, you need to create or update Conditional Access policies to reference the Authentication Contexts used by your Protected Actions: + +1. Navigate to the [Microsoft Entra admin center](https://entra.microsoft.com) +2. Go to **Protection** > **Conditional Access** > **Policies** +3. Create a new policy or edit an existing one +4. Under **Target resources** > **Authentication context**, select the Authentication Context(s) that need to be protected +5. Configure the appropriate grant controls (e.g., require MFA, require compliant device) +6. Enable the policy and save + +Alternatively, if the Protected Action no longer needs step-up authentication, you can remove the Authentication Context assignment from the Protected Action: + +1. Navigate to the [Microsoft Entra admin center](https://entra.microsoft.com) +2. Go to **Identity** > **Roles & admins** > **Protected actions (Preview)** +3. Select the Protected Action +4. Remove or update the Authentication Context assignment + +## Learn more + +- [Protected actions in Microsoft Entra ID](https://learn.microsoft.com/entra/identity/role-based-access-control/protected-actions-overview) +- [Conditional Access: Target resources](https://learn.microsoft.com/entra/identity/conditional-access/concept-conditional-access-cloud-apps) +- [Authentication context in Conditional Access](https://learn.microsoft.com/entra/identity/conditional-access/concept-conditional-access-cloud-apps#authentication-context) + +## Related links + +- [Entra admin center - Conditional Access Policies](https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/ConditionalAccessBlade/~/Overview/fromNav/) +- [Entra admin center - Authentication contexts](https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/ConditionalAccessBlade/~/AuthenticationContext) +- [Entra admin center - Protected actions](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/ProtectedActions) + + +%TestResult% diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 new file mode 100644 index 000000000..0f76e846a --- /dev/null +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -0,0 +1,136 @@ +<# + .Synopsis + Checks if all Protected Actions Authentication Contexts have a conditional access policy referenced. + + .Description + Protected Actions allow organizations to require step-up authentication for sensitive operations by + assigning Authentication Contexts to those actions. However, if an Authentication Context is not + referenced in any Conditional Access policy, the protected action is not effectively protected. + + This test verifies that all Authentication Contexts used by Protected Actions are properly referenced + in at least one Conditional Access policy. + + Learn more: + https://learn.microsoft.com/entra/identity/role-based-access-control/protected-actions-overview + + .Example + Test-MtCaAuthContextProtectedActionsExist + +.LINK + https://maester.dev/docs/commands/Test-MtCaAuthContextProtectedActionsExist +#> +function Test-MtCaAuthContextProtectedActionsExist { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Exists is not a plural.')] + [CmdletBinding()] + [OutputType([bool])] + param () + + if ( ( Get-MtLicenseInformation EntraID ) -eq 'Free' ) { + Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1 + return $null + } + + try { + # Get all authentication contexts + $authContexts = Invoke-MtGraphRequest -RelativeUri 'identity/conditionalAccess/authenticationContextClassReferences' -ApiVersion beta + + if (-not $authContexts -or ($authContexts | Measure-Object).Count -eq 0) { + $testResult = 'No Authentication Contexts are configured in the tenant.' + Add-MtTestResultDetail -Result $testResult + return $true + } + + # Get all protected actions + $protectedActions = Invoke-MtGraphRequest -RelativeUri 'identity/conditionalAccess/authenticationStrength/policies' -ApiVersion beta -ErrorAction SilentlyContinue + $protectedActionContexts = Invoke-MtGraphRequest -RelativeUri 'policies/authenticationStrengthPolicies' -ApiVersion beta -ErrorAction SilentlyContinue + + # Get the role management policy assignments to find protected actions + # Protected Actions are configured through PIM policies + $pimPolicies = Invoke-MtGraphRequest -RelativeUri 'policies/roleManagementPolicyAssignments' -ApiVersion beta -Filter "scopeId eq '/' and scopeType eq 'Directory'" -ErrorAction SilentlyContinue + + # Collect all auth context IDs that are used in protected actions + $authContextsInProtectedActions = [System.Collections.Generic.HashSet[string]]::new() + + # Check role management policies for protected actions configuration + if ($pimPolicies) { + foreach ($assignment in $pimPolicies) { + try { + $policyDetails = Invoke-MtGraphRequest -RelativeUri "policies/roleManagementPolicies/$($assignment.policyId)" -ApiVersion beta -ErrorAction SilentlyContinue + if ($policyDetails.rules) { + foreach ($rule in $policyDetails.rules) { + if ($rule.'@odata.type' -eq '#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule' -and $rule.claimValue) { + [void]$authContextsInProtectedActions.Add($rule.claimValue) + } + } + } + } catch { + Write-Verbose "Could not retrieve policy details for $($assignment.policyId): $_" + } + } + } + + # Get all conditional access policies + $caPolicies = Get-MtConditionalAccessPolicy + + # Collect all auth context IDs referenced in CA policies + $authContextsInCAPolicies = [System.Collections.Generic.HashSet[string]]::new() + foreach ($policy in $caPolicies) { + if ($policy.conditions.applications.includeAuthenticationContextClassReferences) { + foreach ($context in $policy.conditions.applications.includeAuthenticationContextClassReferences) { + [void]$authContextsInCAPolicies.Add($context) + } + } + } + + # Check for auth contexts that are used in protected actions but not in CA policies + $unprotectedContexts = [System.Collections.Generic.List[object]]::new() + + foreach ($authContext in $authContexts) { + # Only check if this auth context is used in protected actions + if ($authContextsInProtectedActions.Contains($authContext.id)) { + if (-not $authContextsInCAPolicies.Contains($authContext.id)) { + $unprotectedContexts.Add(@{ + Id = $authContext.id + DisplayName = $authContext.displayName + Description = $authContext.description + IsAvailable = $authContext.isAvailable + }) + } + } + } + + # Determine result + $result = $unprotectedContexts.Count -eq 0 + + if ($result) { + if ($authContextsInProtectedActions.Count -eq 0) { + $testResult = 'No Authentication Contexts are configured for Protected Actions in this tenant.' + } else { + $testResult = "All Authentication Contexts used in Protected Actions are properly referenced in Conditional Access policies.`n`n" + $testResult += "**Protected Action Auth Contexts with CA policies:**`n`n" + foreach ($authContext in $authContexts) { + if ($authContextsInProtectedActions.Contains($authContext.id)) { + $testResult += "- $($authContext.displayName) ($($authContext.id))`n" + } + } + } + } else { + $testResult = "The following Authentication Contexts are used in Protected Actions but are not referenced by any Conditional Access policy:`n`n" + $testResult += "| Authentication Context | ID | Description |`n" + $testResult += "| --- | --- | --- |`n" + foreach ($context in $unprotectedContexts) { + $displayName = if ($context.DisplayName) { $context.DisplayName } else { "(No name)" } + $description = if ($context.Description) { $context.Description } else { "(No description)" } + $testResult += "| $displayName | $($context.Id) | $description |`n" + } + $testResult += "`n`n⚠️ **Warning**: These Protected Actions are not effectively protected because their Authentication Contexts are not enforced by any Conditional Access policy.`n" + } + + Add-MtTestResultDetail -Result $testResult + return $result + + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} diff --git a/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 b/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 index 6fedf7a6d..662e362a3 100644 --- a/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 +++ b/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 @@ -85,6 +85,10 @@ Test-MtCaApprovedClientApp | Should -Be $true -Because "no policy use the deprecated Approved Client App grant." } + It "MT.1090: All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy. See https://maester.dev/docs/tests/MT.1090" -Tag "MT.1090" { + Test-MtCaAuthContextProtectedActionsExist | Should -Be $true -Because "all Authentication Contexts used in Protected Actions should be enforced by Conditional Access policies." + } + Context "Maester/Entra" -Tag "Entra", "License" { It "MT.1022: All users utilizing a P1 license should be licensed. See https://maester.dev/docs/tests/MT.1022" -Tag "MT.1022" { $LicenseReport = Test-MtCaLicenseUtilization -License "P1" diff --git a/website/docs/tests/maester/MT.1090.md b/website/docs/tests/maester/MT.1090.md new file mode 100644 index 000000000..336e14539 --- /dev/null +++ b/website/docs/tests/maester/MT.1090.md @@ -0,0 +1,49 @@ +--- +title: MT.1090 - All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy. +description: This test checks if all Authentication Contexts used in Protected Actions are properly referenced in at least one Conditional Access policy. +slug: /tests/MT.1090 +sidebar_class_name: hidden +--- + +# Protected Actions Authentication Contexts should have Conditional Access policies + +## Description + +Protected Actions allow organizations to require step-up authentication for sensitive operations by assigning Authentication Contexts to those actions. However, if an Authentication Context is not referenced in any Conditional Access policy, the protected action is not effectively protected. + +This test verifies that all Authentication Contexts used by Protected Actions are properly referenced in at least one Conditional Access policy. + +When a Protected Action has an Authentication Context assigned but that context is not enforced by any Conditional Access policy: +- Users will not be prompted for additional authentication when performing the protected action +- The security benefit of the Protected Action is lost +- The tenant may be exposed to unauthorized sensitive operations + +## How to fix + +If this test fails, you need to create or update Conditional Access policies to reference the Authentication Contexts used by your Protected Actions: + +1. Navigate to the [Microsoft Entra admin center](https://entra.microsoft.com) +2. Go to **Protection** > **Conditional Access** > **Policies** +3. Create a new policy or edit an existing one +4. Under **Target resources** > **Authentication context**, select the Authentication Context(s) that need to be protected +5. Configure the appropriate grant controls (e.g., require MFA, require compliant device) +6. Enable the policy and save + +Alternatively, if the Protected Action no longer needs step-up authentication, you can remove the Authentication Context assignment from the Protected Action: + +1. Navigate to the [Microsoft Entra admin center](https://entra.microsoft.com) +2. Go to **Identity** > **Roles & admins** > **Protected actions (Preview)** +3. Select the Protected Action +4. Remove or update the Authentication Context assignment + +## Learn more + +- [Protected actions in Microsoft Entra ID](https://learn.microsoft.com/entra/identity/role-based-access-control/protected-actions-overview) +- [Conditional Access: Target resources](https://learn.microsoft.com/entra/identity/conditional-access/concept-conditional-access-cloud-apps) +- [Authentication context in Conditional Access](https://learn.microsoft.com/entra/identity/conditional-access/concept-conditional-access-cloud-apps#authentication-context) + +## Related links + +- [Entra admin center - Conditional Access Policies](https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/ConditionalAccessBlade/~/Overview/fromNav/) +- [Entra admin center - Authentication contexts](https://entra.microsoft.com/#view/Microsoft_AAD_ConditionalAccess/ConditionalAccessBlade/~/AuthenticationContext) +- [Entra admin center - Protected actions](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/ProtectedActions) From 532c4f5852d8959cb9e7eab38d2d5117a13fe0d8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:50:49 +0000 Subject: [PATCH 03/20] Remove unused API calls for authentication strength policies Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- .../entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 0f76e846a..2fa017f22 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -40,10 +40,6 @@ function Test-MtCaAuthContextProtectedActionsExist { return $true } - # Get all protected actions - $protectedActions = Invoke-MtGraphRequest -RelativeUri 'identity/conditionalAccess/authenticationStrength/policies' -ApiVersion beta -ErrorAction SilentlyContinue - $protectedActionContexts = Invoke-MtGraphRequest -RelativeUri 'policies/authenticationStrengthPolicies' -ApiVersion beta -ErrorAction SilentlyContinue - # Get the role management policy assignments to find protected actions # Protected Actions are configured through PIM policies $pimPolicies = Invoke-MtGraphRequest -RelativeUri 'policies/roleManagementPolicyAssignments' -ApiVersion beta -Filter "scopeId eq '/' and scopeType eq 'Directory'" -ErrorAction SilentlyContinue From 4ca579702a732c390852358aaed56b12d7fb9e63 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:07:07 -0500 Subject: [PATCH 04/20] Update website/docs/tests/maester/MT.1090.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- website/docs/tests/maester/MT.1090.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1090.md b/website/docs/tests/maester/MT.1090.md index 336e14539..3abcc6fbd 100644 --- a/website/docs/tests/maester/MT.1090.md +++ b/website/docs/tests/maester/MT.1090.md @@ -1,5 +1,5 @@ --- -title: MT.1090 - All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy. +title: MT.1090 - All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy description: This test checks if all Authentication Contexts used in Protected Actions are properly referenced in at least one Conditional Access policy. slug: /tests/MT.1090 sidebar_class_name: hidden From 550d061601a17f9c356189d8070137c9ae5f5a66 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Dec 2025 18:13:11 +0000 Subject: [PATCH 05/20] Address review feedback: rename to MT.1106, filter enabled CA policies, check isEnabled for rules, detect deleted contexts Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- ...st-MtCaAuthContextProtectedActionsExist.md | 2 +- ...t-MtCaAuthContextProtectedActionsExist.ps1 | 26 +++++++++---------- .../Test-ConditionalAccessBaseline.Tests.ps1 | 2 +- .../tests/maester/{MT.1090.md => MT.1106.md} | 6 ++--- 4 files changed, 17 insertions(+), 19 deletions(-) rename website/docs/tests/maester/{MT.1090.md => MT.1106.md} (93%) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md index 282e83a58..36081f7c7 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.md @@ -15,7 +15,7 @@ If this test fails, you need to create or update Conditional Access policies to 2. Go to **Protection** > **Conditional Access** > **Policies** 3. Create a new policy or edit an existing one 4. Under **Target resources** > **Authentication context**, select the Authentication Context(s) that need to be protected -5. Configure the appropriate grant controls (e.g., require MFA, require compliant device) +5. Configure the appropriate grant controls (e.g., require authentication context, require compliant device) 6. Enable the policy and save Alternatively, if the Protected Action no longer needs step-up authentication, you can remove the Authentication Context assignment from the Protected Action: diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 2fa017f22..b63e93405 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -54,7 +54,7 @@ function Test-MtCaAuthContextProtectedActionsExist { $policyDetails = Invoke-MtGraphRequest -RelativeUri "policies/roleManagementPolicies/$($assignment.policyId)" -ApiVersion beta -ErrorAction SilentlyContinue if ($policyDetails.rules) { foreach ($rule in $policyDetails.rules) { - if ($rule.'@odata.type' -eq '#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule' -and $rule.claimValue) { + if ($rule.'@odata.type' -eq '#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule' -and $rule.isEnabled -and $rule.claimValue) { [void]$authContextsInProtectedActions.Add($rule.claimValue) } } @@ -65,8 +65,8 @@ function Test-MtCaAuthContextProtectedActionsExist { } } - # Get all conditional access policies - $caPolicies = Get-MtConditionalAccessPolicy + # Get all enabled conditional access policies + $caPolicies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq 'enabled' } # Collect all auth context IDs referenced in CA policies $authContextsInCAPolicies = [System.Collections.Generic.HashSet[string]]::new() @@ -81,17 +81,15 @@ function Test-MtCaAuthContextProtectedActionsExist { # Check for auth contexts that are used in protected actions but not in CA policies $unprotectedContexts = [System.Collections.Generic.List[object]]::new() - foreach ($authContext in $authContexts) { - # Only check if this auth context is used in protected actions - if ($authContextsInProtectedActions.Contains($authContext.id)) { - if (-not $authContextsInCAPolicies.Contains($authContext.id)) { - $unprotectedContexts.Add(@{ - Id = $authContext.id - DisplayName = $authContext.displayName - Description = $authContext.description - IsAvailable = $authContext.isAvailable - }) - } + foreach ($id in $authContextsInProtectedActions) { + if (-not $authContextsInCAPolicies.Contains($id)) { + $ctx = $authContexts | Where-Object { $_.id -eq $id } | Select-Object -First 1 + $unprotectedContexts.Add(@{ + Id = $id + DisplayName = if ($ctx) { $ctx.displayName } else { '(Deleted or not found)' } + Description = if ($ctx) { $ctx.description } else { '' } + IsAvailable = if ($ctx) { $ctx.isAvailable } else { $null } + }) } } diff --git a/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 b/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 index 662e362a3..e8a970567 100644 --- a/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 +++ b/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 @@ -85,7 +85,7 @@ Test-MtCaApprovedClientApp | Should -Be $true -Because "no policy use the deprecated Approved Client App grant." } - It "MT.1090: All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy. See https://maester.dev/docs/tests/MT.1090" -Tag "MT.1090" { + It "MT.1106: All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy. See https://maester.dev/docs/tests/MT.1106" -Tag "MT.1106" { Test-MtCaAuthContextProtectedActionsExist | Should -Be $true -Because "all Authentication Contexts used in Protected Actions should be enforced by Conditional Access policies." } diff --git a/website/docs/tests/maester/MT.1090.md b/website/docs/tests/maester/MT.1106.md similarity index 93% rename from website/docs/tests/maester/MT.1090.md rename to website/docs/tests/maester/MT.1106.md index 3abcc6fbd..69f1a5b50 100644 --- a/website/docs/tests/maester/MT.1090.md +++ b/website/docs/tests/maester/MT.1106.md @@ -1,7 +1,7 @@ --- -title: MT.1090 - All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy +title: MT.1106 - All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy description: This test checks if all Authentication Contexts used in Protected Actions are properly referenced in at least one Conditional Access policy. -slug: /tests/MT.1090 +slug: /tests/MT.1106 sidebar_class_name: hidden --- @@ -26,7 +26,7 @@ If this test fails, you need to create or update Conditional Access policies to 2. Go to **Protection** > **Conditional Access** > **Policies** 3. Create a new policy or edit an existing one 4. Under **Target resources** > **Authentication context**, select the Authentication Context(s) that need to be protected -5. Configure the appropriate grant controls (e.g., require MFA, require compliant device) +5. Configure the appropriate grant controls (e.g., require authentication context, require compliant device) 6. Enable the policy and save Alternatively, if the Protected Action no longer needs step-up authentication, you can remove the Authentication Context assignment from the Protected Action: From 4d3cad8d55d7301a1d213f00c2c4f21cef00d9f5 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Sat, 20 Dec 2025 19:15:13 -0500 Subject: [PATCH 06/20] Clarify description for MT.1106 test Updated description to specify 'active' Conditional Access policies. --- website/docs/tests/maester/MT.1106.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1106.md b/website/docs/tests/maester/MT.1106.md index 69f1a5b50..43f7fff57 100644 --- a/website/docs/tests/maester/MT.1106.md +++ b/website/docs/tests/maester/MT.1106.md @@ -1,6 +1,6 @@ --- title: MT.1106 - All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy -description: This test checks if all Authentication Contexts used in Protected Actions are properly referenced in at least one Conditional Access policy. +description: This test checks if all Authentication Contexts used in Protected Actions are properly referenced in at least one active Conditional Access policy. slug: /tests/MT.1106 sidebar_class_name: hidden --- From f9ead488250d71b4aeb489781c7b2ed541a65238 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Sat, 20 Dec 2025 19:17:46 -0500 Subject: [PATCH 07/20] Clarify test description for Authentication Contexts Specify that the CA policy must be active/enforced. --- website/docs/tests/maester/MT.1106.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1106.md b/website/docs/tests/maester/MT.1106.md index 43f7fff57..2aec48ac3 100644 --- a/website/docs/tests/maester/MT.1106.md +++ b/website/docs/tests/maester/MT.1106.md @@ -11,9 +11,10 @@ sidebar_class_name: hidden Protected Actions allow organizations to require step-up authentication for sensitive operations by assigning Authentication Contexts to those actions. However, if an Authentication Context is not referenced in any Conditional Access policy, the protected action is not effectively protected. -This test verifies that all Authentication Contexts used by Protected Actions are properly referenced in at least one Conditional Access policy. +This test verifies that all Authentication Contexts used by Protected Actions are properly referenced in at least one active Conditional Access policy. When a Protected Action has an Authentication Context assigned but that context is not enforced by any Conditional Access policy: + - Users will not be prompted for additional authentication when performing the protected action - The security benefit of the Protected Action is lost - The tenant may be exposed to unauthorized sensitive operations From 6f5ed1ff097cb0930423cb3431b724e0cef9004c Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Sat, 20 Dec 2025 19:20:43 -0500 Subject: [PATCH 08/20] Update synopsis and description for clarity --- .../entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index b63e93405..7ac16a583 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -1,13 +1,13 @@ <# .Synopsis - Checks if all Protected Actions Authentication Contexts have a conditional access policy referenced. + Checks if all Protected Actions Authentication Contexts are enforced by a conditional access policy. .Description Protected Actions allow organizations to require step-up authentication for sensitive operations by assigning Authentication Contexts to those actions. However, if an Authentication Context is not - referenced in any Conditional Access policy, the protected action is not effectively protected. + enforced in any Conditional Access policy, the protected action is not effectively protected. - This test verifies that all Authentication Contexts used by Protected Actions are properly referenced + This test verifies that all Authentication Contexts used by Protected Actions are properly enforced in at least one Conditional Access policy. Learn more: From f7e79a272e3f986e093e0b0223bd7a79a989c777 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:11:21 -0500 Subject: [PATCH 09/20] Update website/docs/tests/maester/MT.1106.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- website/docs/tests/maester/MT.1106.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1106.md b/website/docs/tests/maester/MT.1106.md index 2aec48ac3..0310e97a7 100644 --- a/website/docs/tests/maester/MT.1106.md +++ b/website/docs/tests/maester/MT.1106.md @@ -27,7 +27,7 @@ If this test fails, you need to create or update Conditional Access policies to 2. Go to **Protection** > **Conditional Access** > **Policies** 3. Create a new policy or edit an existing one 4. Under **Target resources** > **Authentication context**, select the Authentication Context(s) that need to be protected -5. Configure the appropriate grant controls (e.g., require authentication context, require compliant device) +5. Configure the appropriate grant controls (e.g., require multifactor authentication, require device to be marked as compliant, require approved client app) 6. Enable the policy and save Alternatively, if the Protected Action no longer needs step-up authentication, you can remove the Authentication Context assignment from the Protected Action: From 2221aa70207c2ddaa33b1755ad9f4cec4232dbe2 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:11:48 -0500 Subject: [PATCH 10/20] Update powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 7ac16a583..8a7f698e5 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -42,7 +42,7 @@ function Test-MtCaAuthContextProtectedActionsExist { # Get the role management policy assignments to find protected actions # Protected Actions are configured through PIM policies - $pimPolicies = Invoke-MtGraphRequest -RelativeUri 'policies/roleManagementPolicyAssignments' -ApiVersion beta -Filter "scopeId eq '/' and scopeType eq 'Directory'" -ErrorAction SilentlyContinue + $pimPolicies = Invoke-MtGraphRequest -RelativeUri 'policies/roleManagementPolicyAssignments' -ApiVersion beta -Filter "scopeId eq '/' and scopeType eq 'DirectoryRole'" -ErrorAction SilentlyContinue # Collect all auth context IDs that are used in protected actions $authContextsInProtectedActions = [System.Collections.Generic.HashSet[string]]::new() From e71a633970c426afa1fbcbe17a9f42a169ab1c43 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:12:14 -0500 Subject: [PATCH 11/20] Update powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 8a7f698e5..a565ecdd6 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -25,8 +25,10 @@ function Test-MtCaAuthContextProtectedActionsExist { [OutputType([bool])] param () - if ( ( Get-MtLicenseInformation EntraID ) -eq 'Free' ) { - Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1 + $EntraIDPlan = Get-MtLicenseInformation -Product EntraID + $pim = $EntraIDPlan -eq "P2" -or $EntraIDPlan -eq "Governance" + if (-not $pim) { + Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP2 return $null } From 6f70868b324d7b966e998d9e7c1f767d401a063e Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:13:24 -0500 Subject: [PATCH 12/20] Update powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index a565ecdd6..659fd28bb 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -1,13 +1,13 @@ <# .Synopsis - Checks if all Protected Actions Authentication Contexts are enforced by a conditional access policy. + Checks if all Protected Actions Authentication Contexts are referenced by a conditional access policy. .Description Protected Actions allow organizations to require step-up authentication for sensitive operations by assigning Authentication Contexts to those actions. However, if an Authentication Context is not - enforced in any Conditional Access policy, the protected action is not effectively protected. + referenced in any Conditional Access policy, the protected action is not effectively protected. - This test verifies that all Authentication Contexts used by Protected Actions are properly enforced + This test verifies that all Authentication Contexts used by Protected Actions are properly referenced in at least one Conditional Access policy. Learn more: From bb22969ea2462d31503fb7afc453b2ce58f1fccd Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:13:33 -0500 Subject: [PATCH 13/20] Update tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 b/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 index e8a970567..e65faa5b9 100644 --- a/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 +++ b/tests/Maester/Entra/Test-ConditionalAccessBaseline.Tests.ps1 @@ -86,7 +86,7 @@ } It "MT.1106: All Protected Actions Authentication Contexts should be referenced by a Conditional Access policy. See https://maester.dev/docs/tests/MT.1106" -Tag "MT.1106" { - Test-MtCaAuthContextProtectedActionsExist | Should -Be $true -Because "all Authentication Contexts used in Protected Actions should be enforced by Conditional Access policies." + Test-MtCaAuthContextProtectedActionsExist | Should -Be $true -Because "all Authentication Contexts used in Protected Actions should be referenced by Conditional Access policies." } Context "Maester/Entra" -Tag "Entra", "License" { From d87aa9c522dd491d6daf6d71bb7340d8c8ca07d1 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:13:41 -0500 Subject: [PATCH 14/20] Update website/docs/tests/maester/MT.1106.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- website/docs/tests/maester/MT.1106.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1106.md b/website/docs/tests/maester/MT.1106.md index 0310e97a7..8bc90ad12 100644 --- a/website/docs/tests/maester/MT.1106.md +++ b/website/docs/tests/maester/MT.1106.md @@ -13,7 +13,7 @@ Protected Actions allow organizations to require step-up authentication for sens This test verifies that all Authentication Contexts used by Protected Actions are properly referenced in at least one active Conditional Access policy. -When a Protected Action has an Authentication Context assigned but that context is not enforced by any Conditional Access policy: +When a Protected Action has an Authentication Context assigned but that context is not referenced by any Conditional Access policy: - Users will not be prompted for additional authentication when performing the protected action - The security benefit of the Protected Action is lost From d67059b39c8ec1ded1fde7f6011abda08e8c3ce4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:15:24 +0000 Subject: [PATCH 15/20] Use 'referenced' instead of 'enforced' for consistency in warning message Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- .../maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 659fd28bb..14e04a65b 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -119,7 +119,7 @@ function Test-MtCaAuthContextProtectedActionsExist { $description = if ($context.Description) { $context.Description } else { "(No description)" } $testResult += "| $displayName | $($context.Id) | $description |`n" } - $testResult += "`n`n⚠️ **Warning**: These Protected Actions are not effectively protected because their Authentication Contexts are not enforced by any Conditional Access policy.`n" + $testResult += "`n`n⚠️ **Warning**: These Protected Actions are not effectively protected because their Authentication Contexts are not referenced by any Conditional Access policy.`n" } Add-MtTestResultDetail -Result $testResult From cd8cbf954ff7fb87a354342c9042baa42e51a9a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:18:13 +0000 Subject: [PATCH 16/20] Add UTF-8 BOM to Test-MtCaAuthContextProtectedActionsExist.ps1 Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- .../maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 14e04a65b..5c29ec677 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -1,4 +1,4 @@ -<# +<# .Synopsis Checks if all Protected Actions Authentication Contexts are referenced by a conditional access policy. From 534a4b7eb0f00baaa4c8b0390d21b3a2ca8e3669 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:25:22 +0000 Subject: [PATCH 17/20] Add Test-MtCaAuthContextProtectedActionsExist to module manifest FunctionsToExport Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- powershell/Maester.psd1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index 85e0cc96e..33e45a60a 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -97,7 +97,8 @@ FunctionsToExport = 'Add-MtTestResultDetail', 'Resolve-SpfRecord', 'Send-MtMail', 'Send-MtTeamsMessage', 'Test-MtAppManagementPolicyEnabled', 'Test-MtAppRegistrationsWithSecrets', 'Test-MtSpExchangeAppAccessPolicy', 'Test-MtServicePrincipalsForAllUsers', 'Test-MtAuthenticationPolicyReferencedObjectsExist', - 'Test-MtCaAllAppsExists', 'Test-MtCaApplicationEnforcedRestriction', 'Test-MtCaBlockLegacyExchangeActiveSyncAuthentication', + 'Test-MtCaAllAppsExists', 'Test-MtCaApplicationEnforcedRestriction', 'Test-MtCaAuthContextProtectedActionsExist', + 'Test-MtCaBlockLegacyExchangeActiveSyncAuthentication', 'Test-MtCaBlockLegacyOtherAuthentication', 'Test-MtCaBlockUnknownOrUnsupportedDevicePlatform', 'Test-MtCaDeviceCodeFlow', 'Test-MtCaDeviceComplianceAdminsExists', 'Test-MtCaDeviceComplianceExists', 'Test-MtCaEmergencyAccessExists', 'Test-MtCaEnforceNonPersistentBrowserSession', 'Test-MtCaEnforceSignInFrequency', From 30abcb0445b21660628ea26a9258b8017ad85b22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:52:36 +0000 Subject: [PATCH 18/20] Add verbose logging to diagnose protected actions detection issue Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- .../entra/Test-MtCaAuthContextProtectedActionsExist.ps1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 5c29ec677..623b0e700 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -46,6 +46,8 @@ function Test-MtCaAuthContextProtectedActionsExist { # Protected Actions are configured through PIM policies $pimPolicies = Invoke-MtGraphRequest -RelativeUri 'policies/roleManagementPolicyAssignments' -ApiVersion beta -Filter "scopeId eq '/' and scopeType eq 'DirectoryRole'" -ErrorAction SilentlyContinue + Write-Verbose "Found $($pimPolicies.Count) PIM policy assignments" + # Collect all auth context IDs that are used in protected actions $authContextsInProtectedActions = [System.Collections.Generic.HashSet[string]]::new() @@ -56,7 +58,9 @@ function Test-MtCaAuthContextProtectedActionsExist { $policyDetails = Invoke-MtGraphRequest -RelativeUri "policies/roleManagementPolicies/$($assignment.policyId)" -ApiVersion beta -ErrorAction SilentlyContinue if ($policyDetails.rules) { foreach ($rule in $policyDetails.rules) { + Write-Verbose "Checking rule type: $($rule.'@odata.type'), isEnabled: $($rule.isEnabled), claimValue: $($rule.claimValue)" if ($rule.'@odata.type' -eq '#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule' -and $rule.isEnabled -and $rule.claimValue) { + Write-Verbose "Found authentication context in protected action: $($rule.claimValue)" [void]$authContextsInProtectedActions.Add($rule.claimValue) } } @@ -67,6 +71,8 @@ function Test-MtCaAuthContextProtectedActionsExist { } } + Write-Verbose "Total authentication contexts found in protected actions: $($authContextsInProtectedActions.Count)" + # Get all enabled conditional access policies $caPolicies = Get-MtConditionalAccessPolicy | Where-Object { $_.state -eq 'enabled' } From ffd203d4c907679f1972f6f1456423a57d00aa2c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:32:02 +0000 Subject: [PATCH 19/20] Fix Protected Actions detection by using correct API endpoint (roleManagement/directory/resourceNamespaces) Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- ...t-MtCaAuthContextProtectedActionsExist.ps1 | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index 623b0e700..bd1c14277 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -42,31 +42,36 @@ function Test-MtCaAuthContextProtectedActionsExist { return $true } - # Get the role management policy assignments to find protected actions - # Protected Actions are configured through PIM policies - $pimPolicies = Invoke-MtGraphRequest -RelativeUri 'policies/roleManagementPolicyAssignments' -ApiVersion beta -Filter "scopeId eq '/' and scopeType eq 'DirectoryRole'" -ErrorAction SilentlyContinue - - Write-Verbose "Found $($pimPolicies.Count) PIM policy assignments" + # Get Protected Actions with authentication contexts + # Protected Actions are accessed through roleManagement/directory/resourceNamespaces + try { + $resourceNamespaces = Invoke-MtGraphRequest -RelativeUri 'roleManagement/directory/resourceNamespaces' -ApiVersion beta -ErrorAction SilentlyContinue + Write-Verbose "Found $($resourceNamespaces.Count) resource namespaces" + } catch { + Write-Verbose "Could not retrieve resource namespaces: $_" + $resourceNamespaces = @() + } # Collect all auth context IDs that are used in protected actions $authContextsInProtectedActions = [System.Collections.Generic.HashSet[string]]::new() - # Check role management policies for protected actions configuration - if ($pimPolicies) { - foreach ($assignment in $pimPolicies) { + # Check each resource namespace for protected actions with authentication contexts + if ($resourceNamespaces) { + foreach ($namespace in $resourceNamespaces) { try { - $policyDetails = Invoke-MtGraphRequest -RelativeUri "policies/roleManagementPolicies/$($assignment.policyId)" -ApiVersion beta -ErrorAction SilentlyContinue - if ($policyDetails.rules) { - foreach ($rule in $policyDetails.rules) { - Write-Verbose "Checking rule type: $($rule.'@odata.type'), isEnabled: $($rule.isEnabled), claimValue: $($rule.claimValue)" - if ($rule.'@odata.type' -eq '#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule' -and $rule.isEnabled -and $rule.claimValue) { - Write-Verbose "Found authentication context in protected action: $($rule.claimValue)" - [void]$authContextsInProtectedActions.Add($rule.claimValue) + # Get resource actions for this namespace + $resourceActions = Invoke-MtGraphRequest -RelativeUri "roleManagement/directory/resourceNamespaces/$($namespace.id)/resourceActions" -ApiVersion beta -ErrorAction SilentlyContinue + if ($resourceActions) { + foreach ($action in $resourceActions) { + # Check if this action has an authentication context requirement + if ($action.authenticationContextId) { + Write-Verbose "Found protected action '$($action.name)' with authentication context: $($action.authenticationContextId)" + [void]$authContextsInProtectedActions.Add($action.authenticationContextId) } } } } catch { - Write-Verbose "Could not retrieve policy details for $($assignment.policyId): $_" + Write-Verbose "Could not retrieve resource actions for namespace $($namespace.id): $_" } } } From 1049fa3ececd732d0279b8d2c222c4b2c8faae7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:44:43 +0000 Subject: [PATCH 20/20] Add enhanced verbose logging to debug Protected Actions structure and property names Co-authored-by: SamErde <20478745+SamErde@users.noreply.github.com> --- ...t-MtCaAuthContextProtectedActionsExist.ps1 | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 index bd1c14277..791dd2a14 100644 --- a/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 +++ b/powershell/public/maester/entra/Test-MtCaAuthContextProtectedActionsExist.ps1 @@ -57,16 +57,36 @@ function Test-MtCaAuthContextProtectedActionsExist { # Check each resource namespace for protected actions with authentication contexts if ($resourceNamespaces) { + $namespaceCount = 0 foreach ($namespace in $resourceNamespaces) { + $namespaceCount++ try { # Get resource actions for this namespace $resourceActions = Invoke-MtGraphRequest -RelativeUri "roleManagement/directory/resourceNamespaces/$($namespace.id)/resourceActions" -ApiVersion beta -ErrorAction SilentlyContinue if ($resourceActions) { + Write-Verbose "Namespace $namespaceCount/$($resourceNamespaces.Count) ($($namespace.id)): Found $($resourceActions.Count) resource actions" foreach ($action in $resourceActions) { + # Debug: Log all properties of the first few actions to understand structure + if ($namespaceCount -le 3 -and $resourceActions.IndexOf($action) -le 2) { + Write-Verbose "Sample action properties: $($action | ConvertTo-Json -Depth 2 -Compress)" + } + # Check if this action has an authentication context requirement + # Try multiple possible property names + $authContextId = $null if ($action.authenticationContextId) { - Write-Verbose "Found protected action '$($action.name)' with authentication context: $($action.authenticationContextId)" - [void]$authContextsInProtectedActions.Add($action.authenticationContextId) + $authContextId = $action.authenticationContextId + } elseif ($action.authenticationContext) { + $authContextId = $action.authenticationContext + } elseif ($action.authContext) { + $authContextId = $action.authContext + } elseif ($action.PSObject.Properties['authenticationContextId']) { + $authContextId = $action.PSObject.Properties['authenticationContextId'].Value + } + + if ($authContextId) { + Write-Verbose "Found protected action '$($action.name)' with authentication context: $authContextId" + [void]$authContextsInProtectedActions.Add($authContextId) } } }