Skip to content

Add 9 Global Secure Access checks (MT.1187–MT.1195) [Preview]#1992

Open
crmhh wants to merge 19 commits into
maester365:mainfrom
crmhh:feat/gsa-checks
Open

Add 9 Global Secure Access checks (MT.1187–MT.1195) [Preview]#1992
crmhh wants to merge 19 commits into
maester365:mainfrom
crmhh:feat/gsa-checks

Conversation

@crmhh

@crmhh crmhh commented Jul 24, 2026

Copy link
Copy Markdown

📑 Description

Adds nine Microsoft Entra Global Secure Access checks (Private Access / Internet Access configuration hygiene), tagged Preview, using test ids MT.1187–MT.1195 (reserved on #697 — tracking issue, not closed by this PR).

Global Secure Access currently has no Maester coverage. These checks catch common, high-impact GSA misconfigurations that are easy to introduce and hard to troubleshoot — nested-group assignment traps that surface only as silent DNS timeouts, break-glass lockout through the Compliant Network control, sign-in frequency on Quick Access causing repeated MFA prompts on background DNS, and private-app segment / Conditional Access gaps that break least privilege. All nine were validated against a live GSA tenant.

The set is intentionally scoped against the Global Secure Access checks in the Microsoft Zero Trust Assessment (which are also being migrated into Maester) to avoid duplication — checks already covered equivalently by ZTA were left out, so these nine are either unique to Maester or add a failure mode ZTA does not flag.

New checks (public Test-MtGsa* function + companion .md + Pester test in Describe "Maester/Entra", tagged Preview, + website/docs/tests/maester/MT.119x.md):

Test id Function Asserts
MT.1187 Test-MtGsaM365ProfileEnabled Microsoft 365 traffic forwarding profile is enabled
MT.1188 Test-MtGsaPrivateAccessAppCompliantDevice Private Access apps require a managed device via Conditional Access
MT.1189 Test-MtGsaForwardingProfileAssignmentNotNested Traffic-forwarding-profile assignment groups are not nested
MT.1190 Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup No Private Access app on the Default connector group
MT.1191 Test-MtGsaCompliantNetworkBreakGlassExcluded Break-glass accounts excluded from Compliant Network policies (honors group membership)
MT.1192 Test-MtGsaPrivateAccessAppAssignmentNotNested Private / Quick Access app assignment groups are not nested
MT.1193 Test-MtGsaPrivateAccessAppSegmentHygiene Segments avoid broad/risky destinations (wildcard FQDN, single-label/Kerberos, dnsSuffix, broad IPv4 mask)
MT.1194 Test-MtGsaBaselineThreatIntelligenceEnforced Baseline security profile enforces a threat-intelligence floor
MT.1195 Test-MtGsaQuickAccessNoSignInFrequency No sign-in-frequency control reaches Quick Access (role/guest/risk/browser tiered to review; policy allow-list supported)

Supporting changes

  • 3 internal helpers: Get-MtPrivateAccessApplication, Get-MtCompliantNetworkPolicy, Get-MtEmergencyAccessAccount
  • Get-MtGraphScope: add NetworkAccess.Read.All (+ permissions doc entry)
  • Maester.psd1: export the 9 new functions

Closes #

✅ Checks

  • My pull request adheres to the code style of this project.
  • My code requires changes to the documentation.
  • I have updated the documentation as required.
  • The build and unit tests pass after running /powershell/tests/pester.ps1 locally.

ℹ️ Additional Information

  • All checks are read-only and degrade gracefully (return $null / skip) on tenants without the relevant GSA capability (no M365/Internet profile, no Private Access apps, no connector groups, no filtering profiles), so they are safe to run on any tenant.
  • Required Graph permission added: NetworkAccess.Read.All (read-only).
  • Tagged Preview.
  • MT.1195 includes optional tiering (directory-role / guest / risk-gated / browser-only policies are surfaced as review rather than fail) and an allow-list via the GsaQuickAccessSignInFrequencyAllowedPolicies global setting. Happy to simplify this for a first iteration if preferred.
  • The general / build / lint suite (pester.ps1: Build, GeneratedFileFormatting, Help, MaesterTestTags, Manifest, Module, PSScriptAnalyzer, PublishedModuleResultDetail) passes with no failures.

Summary by CodeRabbit

  • New Features
    • Added Global Secure Access assessment cmdlets and checks for threat-intelligence enforcement, compliant-network break-glass exclusion, traffic forwarding/profile enablement, and Private Access configuration hygiene (including nesting rules, managed-device coverage, connector group placement, segment destination scope, and Quick Access sign-in frequency).
    • Expanded the default Graph permission scopes to include NetworkAccess.Read.All.
  • Documentation
    • Added new remediation guides for the new Global Secure Access findings and updated permissions documentation.
  • Tests
    • Added Pester coverage for the new checks.

crmhh and others added 17 commits June 21, 2026 16:38
Adds a Maester check (helper, companion doc, Pester test, website doc) that
verifies the Microsoft 365 traffic forwarding profile in Global Secure Access
is enabled. Enabling it unlocks source IP restoration, the Compliant Network
signal, Universal Tenant Restrictions, and network access traffic logging.

Tagged as Preview because it uses the beta networkAccess Graph API.
Test ID is a MT.XXXX placeholder pending reservation on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Renames the provisional MT.XXXX test ID to MT.XXX1 so each in-flight GSA check
uses a unique, greppable placeholder ahead of reserving real IDs on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a Maester check (helper, companion doc, Pester test, website doc) that
verifies Global Secure Access Conditional Access signaling is enabled, which
powers source IP restoration and the Compliant Network signal for token replay
protection.

Tagged as Preview because it uses the beta networkAccess Graph API
(networkAccess/settings/conditionalAccess, signalingStatus). Test ID is a
MT.XXX2 placeholder pending reservation on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…checks

Adds four Maester checks (helper + companion doc + Pester test + website doc each)
plus the internal Get-MtPrivateAccessApplication helper:

- MT.XXX3 Private Access apps are covered by an MFA Conditional Access policy
- MT.XXX4 Private Access apps are covered by a managed-device Conditional Access policy
- MT.XXX5 traffic forwarding profile assignment groups are not nested
- MT.XXX6 Private Access apps do not use the Default connector group

Entra Private Access apps are enumerated by service principal tag
(IsAccessibleViaZTNAClient / NetworkAccessQuickAccessApplication) because the
application onPremisesPublishing property is not exposed via Graph. MFA detection
accepts an authentication strength; managed-device accepts compliant or hybrid
joined. The forwarding-profile nesting check targets the traffic forwarding profile
service principals (Microsoft does not honor nested groups for profile assignment).

All verified read-only against a tenant. Tagged Preview (beta networkAccess /
servicePrincipals APIs). Test IDs are MT.XXX3-6 placeholders pending reservation on maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a Maester check (helper, companion doc, Pester test, website doc) that verifies
every in-use Microsoft Entra private network connector group (connectorGroupType
applicationProxy) has at least two active connectors, so a single connector outage
does not break access to the apps it serves. Connector groups with no connectors are
treated as unused and skipped.

Reads onPremisesPublishingProfiles/applicationProxy/connectorGroups and /members - both
work read-only with Directory.Read.All (already a default Maester scope), despite the
docs listing Directory.ReadWrite.All. Tagged Preview (beta API). Test ID MT.XXX7 is a
placeholder pending reservation on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Global Secure Access checks (MT.XXX1 M365 profile, MT.XXX2 Conditional Access
signaling) read beta networkAccess endpoints that require the read-only
NetworkAccess.Read.All scope. Add it to the default scope set and document it in
the permissions reference, keeping alphabetical order.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…warding profile check

Reuses the existing Get-MtGroupMember helper instead of a raw Graph call, aligning
with established Maester patterns and inheriting its handling of deleted/GDAP groups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…check

Adds a Maester check (helper, companion doc, Pester test, website doc) that verifies
no group assigned (appRoleAssignedTo) to a Private Access or Quick Access application
contains a nested group. Enterprise app assignment grants access to direct/dynamic
members only and does not cascade to nested groups, so a nested assignment group
silently leaves members without access.

Complements MT.XXX5 (forwarding profile assignment) to cover all GSA app-assignment
surfaces. Reuses Get-MtPrivateAccessApplication and Get-MtGroupMember. Conditional
Access scoping honors nested groups, so the MFA/managed-device checks are unaffected.
Test ID MT.XXX8 is a placeholder pending reservation on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…hecks

Adds two Maester checks plus two internal helpers:

- MT.XXX9  Test-MtGsaCompliantNetworkPolicy: an enabled CA policy enforces the
  Compliant Network control (block when not on a compliant network) and excludes the
  Microsoft Intune + Intune Enrollment apps so device onboarding is not blocked.
- MT.XXX10 Test-MtGsaCompliantNetworkBreakGlassExcluded: every Compliant Network
  enforcement policy excludes the configured emergency-access (break-glass) accounts.

Get-MtCompliantNetworkPolicy resolves the compliantNetworkNamedLocation and the
enabled block policies that reference it (shared by both checks). Get-MtEmergencyAccessAccount
resolves EmergencyAccessAccounts from maester-config.json (by Id or UPN/mail) to object
IDs. Verified read-only against a tenant. Tagged Preview. Test IDs MT.XXX9/10 are
placeholders pending reservation on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uick Access CA checks

Adds four Maester checks (helper + companion doc + Pester test + website doc each):

- MT.XXX11 Test-MtGsaPrivateAccessAppSegmentHygiene: no Private Access app segment uses a
  broad/risky destination (dnsSuffix, wildcard FQDN, single-label FQDN, all-IP).
- MT.XXX12 Test-MtGsaInternetAccessFilteringEnforced: when the Internet Access profile is
  enabled, at least one filtering profile has an active policy (no unfiltered egress).
- MT.XXX13 Test-MtGsaBaselineThreatIntelligenceEnforced: the baseline security profile
  (priority 65000) has an enabled threat-intelligence policy linked.
- MT.XXX14 Test-MtGsaQuickAccessNoSignInFrequency: no enabled sign-in frequency CA control
  covers the Quick Access app (avoids DNS-triggered re-auth prompts).

Graph shapes verified against MS Learn (ipApplicationSegment destinationType enum;
filteringProfile priority/policies policyLink @odata.type + state; signInFrequency session
control). Read-only via existing default scopes. Tagged Preview. Test IDs MT.XXX11-14 are
placeholders pending reservation on issue maester365#697.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…candidates

Reconcile the GSA check set against microsoft/zerotrustassessment before the
upstream PR to maester365/maester:

- Remove GK.GSA.02/03/04 (ZTA 25466/25380/25396 already cover them; 25396 is the
  stronger implementation) - function, doc, Pester test, website MT doc, and the
  Maester.psd1 export entries.
- Remove GK.GSA.09/12 from the fork; their fork-only logic (Intune-enrollment
  minimum exclusions; baseline-only filtering awareness) is preserved separately
  for merge into ZTA 25379/25407.
- Drop the now-dangling Test-MtGsaCompliantNetworkPolicy reference from the
  GK.GSA.08 result message.

9 GSA checks remain in the fork as the clean upstream-PR set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… hygiene; surface managed-device coverage

Improvements found during live lab counter-testing against a Global Secure Access tenant:

- GK.GSA.08 (Compliant Network break-glass): an emergency account excluded via
  (nested) group membership is now recognized, not only a direct user/group
  exclusion - resolves users/{id}/transitiveMemberOf and matches against the
  policy excludeGroups, mirroring how Conditional Access evaluates exclusions.
- GK.GSA.11 (segment hygiene): replace the UI-unreachable exact 0.0.0.0/0 match
  with a mask-based broad-range check (flags IPv4 masks broader than /16; the
  portal's broadest selectable mask is /1). IPv4-only, as GSA does not acquire IPv6.
- GK.GSA.05 (managed device): on pass, list each app and its covering policy
  (app-specific vs 'All cloud apps'), so a surprising pass - app excluded from one
  policy but still swept in by a broad one - is transparent.

Companion docs updated. Verified against the lab: break-glass passes (excluded via
group); induced misconfigurations flip the other checks to fail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ased tiering

GK.GSA.14 no longer resolves Quick Access assignment / group membership. An enabled
sign-in-frequency policy that targets Quick Access is a Fail, unless it falls into a
category that does not drive routine DNS prompts (surfaced as Review):
directory-role-only, guest / external-user scoped, risk-gated, or browser-only.
Reviewed exceptions are allow-listed by policy id or display name via the
GsaQuickAccessSignInFrequencyAllowedPolicies global setting (reported as Accepted).

Also fixes a false positive where @($null).Count is 1 in PowerShell, which made every
policy read as risk-gated; emptiness is now tested with a null-safe helper.

Verified against a live lab: role / guest / risk / browser policies tier to Review,
allow-listed policies to Accepted, and only genuine Quick-Access-targeting policies fail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the MT.XXX placeholders with the numbers reserved on maester365#697:

- MT.1187 Test-MtGsaM365ProfileEnabled
- MT.1188 Test-MtGsaPrivateAccessAppCompliantDevice
- MT.1189 Test-MtGsaForwardingProfileAssignmentNotNested
- MT.1190 Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup
- MT.1191 Test-MtGsaCompliantNetworkBreakGlassExcluded
- MT.1192 Test-MtGsaPrivateAccessAppAssignmentNotNested
- MT.1193 Test-MtGsaPrivateAccessAppSegmentHygiene
- MT.1194 Test-MtGsaBaselineThreatIntelligenceEnforced
- MT.1195 Test-MtGsaQuickAccessNoSignInFrequency

Renames website/docs/tests/maester/MT.XXXn.md to MT.119x.md and updates the
It block, tag, and docs URL in each Pester test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The helper returns an object array but declared no [OutputType], failing the
PSUseOutputTypeCorrectly rule in the general test suite. Add [OutputType([Object[]])].
The general / build / lint suite (Build, GeneratedFileFormatting, Help,
MaesterTestTags, Manifest, Module, PSScriptAnalyzer, PublishedModuleResultDetail)
now passes with no failures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@crmhh
crmhh requested review from a team as code owners July 24, 2026 13:21
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a404ea2a-f842-4fc5-89a1-29d835f790a7

📥 Commits

Reviewing files that changed from the base of the PR and between 0cfcb2e and 6ba5060.

📒 Files selected for processing (3)
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.ps1
  • website/docs/tests/maester/MT.1193.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • website/docs/tests/maester/MT.1193.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.ps1

📝 Walkthrough

Walkthrough

Adds eight Global Secure Access compliance checks, Graph data helpers, the required permission scope, exported functions, Pester tests, and documentation for profile, Conditional Access, Private Access, connector, segment, and Quick Access controls.

Changes

Global Secure Access test suite

Layer / File(s) Summary
Graph permissions and data helpers
powershell/internal/*, powershell/public/Get-MtGraphScope.ps1, website/docs/sections/permissions.md, powershell/Maester.psd1
Adds Graph retrieval helpers, the NetworkAccess.Read.All scope, permission documentation updates, and module export wiring.
Profile and Conditional Access checks
powershell/public/maester/globalsecureaccess/*Profile*, *BaselineThreatIntelligence*, *CompliantNetwork*, tests/Maester/GlobalSecureAccess/*, website/docs/tests/maester/MT.1187.md, MT.1189.md, MT.1191.md, MT.1194.md
Adds checks and coverage for M365 profile enablement, forwarding-profile nesting, baseline threat intelligence, and emergency-account exclusions.
Private Access and Quick Access checks
powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccess*, Test-MtGsaQuickAccess*, tests/Maester/GlobalSecureAccess/*PrivateAccess*, *QuickAccess*, website/docs/tests/maester/MT.1188.mdMT.1193.md, MT.1195.md
Adds checks and documentation for managed-device coverage, nested assignments, connector groups, segment hygiene, and Quick Access sign-in frequency.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MaesterTest
  participant GsaCheck
  participant MicrosoftGraph
  participant TestResultDetail
  MaesterTest->>GsaCheck: invoke Global Secure Access check
  GsaCheck->>MicrosoftGraph: retrieve profiles, applications, or policies
  MicrosoftGraph-->>GsaCheck: return configuration data
  GsaCheck->>TestResultDetail: record pass, failure, or skipped result
  GsaCheck-->>MaesterTest: return boolean or null
Loading

Possibly related PRs

Suggested labels: enhancement, maester-test, documentation, maester-core

Suggested reviewers: merill

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: nine new Global Secure Access checks in the MT.1187–MT.1195 range.
Description check ✅ Passed The PR description includes the required Description, Checks, and Additional Information sections and adequately summarizes scope, behavior, and validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@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: 7

🧹 Nitpick comments (1)
powershell/internal/Get-MtPrivateAccessApplication.ps1 (1)

30-30: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid full service-principal inventory reads for Global Secure Access lookups. Target the known resources at Graph instead of enumerating the directory.

  • powershell/internal/Get-MtPrivateAccessApplication.ps1#L30-L30: filter servicePrincipals by the two known tags and select only required fields.
  • powershell/public/maester/globalsecureaccess/Test-MtGsaForwardingProfileAssignmentNotNested.ps1#L39-L40: query networkAccess/forwardingProfiles and follow each profile’s service-principal reference.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@powershell/internal/Get-MtPrivateAccessApplication.ps1` at line 30, Update
powershell/internal/Get-MtPrivateAccessApplication.ps1 at lines 30-30 to query
servicePrincipals with a Graph filter for the two known Global Secure Access
tags and select only the fields required by the lookup. Update
powershell/public/maester/globalsecureaccess/Test-MtGsaForwardingProfileAssignmentNotNested.ps1
at lines 39-40 to query networkAccess/forwardingProfiles and resolve each
profile’s service-principal reference instead of enumerating all service
principals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@powershell/internal/Get-MtCompliantNetworkPolicy.ps1`:
- Around line 28-34: Update the policy filter in Get-MtCompliantNetworkPolicy to
require the documented scope: includeLocations must contain 'All' and
excludeLocations must contain a compliant network ID. Remove the current
condition that accepts compliant IDs in includeLocations or any exclusion, while
preserving the enabled and block grant-control requirements.

In `@powershell/internal/Get-MtEmergencyAccessAccount.ps1`:
- Around line 56-58: Update the catch handling in Get-MtEmergencyAccessAccount
so resolution failures are preserved in the returned result rather than only
emitted via Write-Warning and omitted from $resolved. Represent the failed
configured account in a way the consuming check can detect and report an
indeterminate result, while keeping successfully resolved accounts unchanged.

In
`@powershell/public/maester/globalsecureaccess/Test-MtGsaCompliantNetworkBreakGlassExcluded.ps1`:
- Around line 56-64: Update the membership lookup in the account-processing
block so both user accounts and group accounts resolve transitive memberships,
using the users/{id}/transitiveMemberOf endpoint for users and
groups/{id}/transitiveMemberOf for group Type values. Remove the inner catch
that converts Graph failures into an empty group list, allowing the surrounding
error handling to skip indeterminate checks.

In
`@powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppCompliantDevice.ps1`:
- Around line 45-50: Update the compliance-policy filter in
Test-MtGsaPrivateAccessAppCompliantDevice to account for grantControls.operator
semantics: retain policies that require compliantDevice or domainJoinedDevice on
every satisfiable path, and exclude OR policies where another control such as
mfa can satisfy the grant independently. Preserve enabled-policy filtering and
support AND policies only when a managed-device control is present.

In
`@powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup.ps1`:
- Around line 44-55: Update the Graph lookup flow in the test function
containing $appObject, $connectorGroup, and $onDefault so unresolved application
registrations and connectorGroup request failures are not converted into normal
no-finding results. Remove the continue for a missing $appObject and the inner
catch that assigns $connectorGroup = $null; allow these failures to propagate to
the existing outer catch, producing the skip/unknown outcome instead of
returning $true.

In
`@powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.ps1`:
- Around line 46-51: Update the segment retrieval in
Test-MtGsaPrivateAccessAppSegmentHygiene to use the documented per-application
onPremisesPublishing application-segment endpoint for every Private Access
application, rather than the flat applicationSegments collection. Enumerate the
relevant applications and expand or request each app’s segments before
evaluating destinations, while preserving the existing no-segments result and
catch behavior.

In `@website/docs/tests/maester/MT.1193.md`:
- Line 17: Update the All-IP destinations bullet in MT.1193.md to remove the
IPv6 `::/0` example and describe the check as IPv4-only, matching the
implementation and the scope documented in
Test-MtGsaPrivateAccessAppSegmentHygiene.md.

---

Nitpick comments:
In `@powershell/internal/Get-MtPrivateAccessApplication.ps1`:
- Line 30: Update powershell/internal/Get-MtPrivateAccessApplication.ps1 at
lines 30-30 to query servicePrincipals with a Graph filter for the two known
Global Secure Access tags and select only the fields required by the lookup.
Update
powershell/public/maester/globalsecureaccess/Test-MtGsaForwardingProfileAssignmentNotNested.ps1
at lines 39-40 to query networkAccess/forwardingProfiles and resolve each
profile’s service-principal reference instead of enumerating all service
principals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2080547f-54ca-4554-a8ae-7ab6313b92d4

📥 Commits

Reviewing files that changed from the base of the PR and between 463b40d and 4679864.

📒 Files selected for processing (42)
  • powershell/Maester.psd1
  • powershell/internal/Get-MtCompliantNetworkPolicy.ps1
  • powershell/internal/Get-MtEmergencyAccessAccount.ps1
  • powershell/internal/Get-MtPrivateAccessApplication.ps1
  • powershell/public/Get-MtGraphScope.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaBaselineThreatIntelligenceEnforced.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaBaselineThreatIntelligenceEnforced.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaCompliantNetworkBreakGlassExcluded.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaCompliantNetworkBreakGlassExcluded.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaForwardingProfileAssignmentNotNested.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaForwardingProfileAssignmentNotNested.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaM365ProfileEnabled.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaM365ProfileEnabled.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppAssignmentNotNested.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppAssignmentNotNested.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppCompliantDevice.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppCompliantDevice.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaPrivateAccessAppSegmentHygiene.ps1
  • powershell/public/maester/globalsecureaccess/Test-MtGsaQuickAccessNoSignInFrequency.md
  • powershell/public/maester/globalsecureaccess/Test-MtGsaQuickAccessNoSignInFrequency.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaBaselineThreatIntelligenceEnforced.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaCompliantNetworkBreakGlassExcluded.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaForwardingProfileAssignmentNotNested.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaM365ProfileEnabled.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaPrivateAccessAppAssignmentNotNested.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaPrivateAccessAppCompliantDevice.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaPrivateAccessAppSegmentHygiene.Tests.ps1
  • tests/Maester/GlobalSecureAccess/Test-MtGsaQuickAccessNoSignInFrequency.Tests.ps1
  • website/docs/sections/permissions.md
  • website/docs/tests/maester/MT.1187.md
  • website/docs/tests/maester/MT.1188.md
  • website/docs/tests/maester/MT.1189.md
  • website/docs/tests/maester/MT.1190.md
  • website/docs/tests/maester/MT.1191.md
  • website/docs/tests/maester/MT.1192.md
  • website/docs/tests/maester/MT.1193.md
  • website/docs/tests/maester/MT.1194.md
  • website/docs/tests/maester/MT.1195.md

Comment thread powershell/internal/Get-MtCompliantNetworkPolicy.ps1 Outdated
Comment thread powershell/internal/Get-MtEmergencyAccessAccount.ps1
Comment thread website/docs/tests/maester/MT.1193.md Outdated
crmhh and others added 2 commits July 24, 2026 16:30
…tor semantics, per-app segments)

Addresses the CodeRabbit review on maester365#1992:

- Get-MtCompliantNetworkPolicy: require the documented enforcement pattern
  (include All, exclude Compliant Network, block) instead of any CN reference.
- Get-MtEmergencyAccessAccount: fail on unresolved break-glass accounts so the
  consuming check reports indeterminate instead of a false pass.
- Test-MtGsaCompliantNetworkBreakGlassExcluded: resolve transitiveMemberOf for
  group accounts too; let Graph failures propagate (no silent empty list).
- Test-MtGsaPrivateAccessAppCompliantDevice: honor grantControls.operator - an
  OR policy where mfa alone can satisfy the grant no longer counts as managed-device.
- Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup: let unresolved apps /
  Graph failures propagate to skip instead of a false "not on Default".
- Test-MtGsaPrivateAccessAppSegmentHygiene: read segments from each app's
  onPremisesPublishing configuration (per-app) instead of the flat collection.
- Get-MtPrivateAccessApplication: filter servicePrincipals by tag server-side.
- MT.1193.md: describe the IP check as IPv4-only (drop ::/0).

Validated: general/lint suite (PSScriptAnalyzer 971/0) and a live GSA tenant run
(9/9 executed, no errors or skips; the per-app segment read now also surfaces
Quick Access segments the flat endpoint missed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…servicePrincipalName

Based on live Quick Access data:
- servicePrincipalName segments (Kerberos SPNs such as HTTP/*) are a legitimate
  Private Access construct and are no longer evaluated.
- dnsSuffix is flagged only when it is a bare top-level domain (single label,
  e.g. net / local); a normal scoped suffix such as contoso.com is the recommended
  resolution path and is no longer flagged.

Companion and website docs updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@crmhh

crmhh commented Jul 24, 2026

Copy link
Copy Markdown
Author

Thanks for the thorough review! All actionable comments and the nitpick are addressed in 0cfcb2e5 and 6ba50600.

Functional correctness / security

  • Get-MtCompliantNetworkPolicy — now requires the documented enforcement pattern (include All + exclude Compliant Network + block) instead of any CN reference.
  • Get-MtEmergencyAccessAccount — an unresolved break-glass account now fails the lookup, so the consuming check reports an indeterminate result instead of a false pass.
  • Test-MtGsaCompliantNetworkBreakGlassExcluded — resolves transitiveMemberOf for group accounts too, and lets Graph failures propagate (no silent empty list).
  • Test-MtGsaPrivateAccessAppCompliantDevice — honors grantControls.operator: an OR policy where mfa alone can satisfy the grant no longer counts as requiring a managed device.
  • Test-MtGsaPrivateAccessAppNotOnDefaultConnectorGroup — unresolved apps / Graph failures now propagate to a skip instead of a false "not on Default".
  • Test-MtGsaPrivateAccessAppSegmentHygiene — reads segments from each app's onPremisesPublishing configuration (per-app). Nice catch: against a live tenant this actually surfaces Quick Access segments that the flat applicationSegments collection had missed.

Docs / nitpick

  • MT.1193.md — the IP check is documented as IPv4-only (dropped ::/0).
  • Get-MtPrivateAccessApplication — filters servicePrincipals by tag server-side (with $count) instead of enumerating the directory.

Follow-up refinement (from live Quick Access data): segment hygiene now ignores servicePrincipalName segments (Kerberos SPNs such as HTTP/*) and only flags a dnsSuffix when it is a bare top-level domain — a normal scoped suffix such as contoso.com is the recommended resolution path and is no longer flagged.

Validated end to end: the general/lint suite (pester.ps1, PSScriptAnalyzer 971/0) passes, and a live Global Secure Access tenant run executes all checks with no errors or skips — the fail-safe changes were specifically checked for over-skipping.

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.

1 participant