-
Notifications
You must be signed in to change notification settings - Fork 126
Network 25377: Users accessing external applications from corporate devices are blocked unless explicitly authorized by tenant restrictions policies #838
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
Merged
Merged
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
3e52c6d
added test
ashwinikarke c7a7847
taken pull
ashwinikarke 4e734be
taken pull
ashwinikarke 3879f8f
updated table
ashwinikarke 895f9e0
updated portal link
ashwinikarke 53867ff
resolved copilot comments
ashwinikarke 4acb5dd
resolved PR comments
ashwinikarke 9c2c2c7
removed who when where
ashwinikarke 67eaff9
removed who when where
ashwinikarke ec679ee
added ellipsis
ashwinikarke aa0f6f7
added ellipsis
ashwinikarke c1fa02e
updated dev status
ashwinikarke 9bf8aa5
taken pull
ashwinikarke c38ae18
updated code
ashwinikarke 45e5803
taken pull
ashwinikarke bc9410b
added Database parameter
ashwinikarke 3f1d1b5
added Database parameter
ashwinikarke File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| Without Universal Tenant Restrictions (UTR) configured, users on corporate devices and networks can authenticate to unauthorized external Microsoft Entra tenants and access cloud applications using external identities, creating a significant data exfiltration vector. A threat actor who has compromised user credentials or established persistence on a corporate device can authenticate to a tenant they control using personal or external organizational identities, bypassing traditional network security controls that cannot inspect encrypted authentication traffic to Microsoft identity endpoints. Once authenticated to an external tenant, the actor can access Microsoft Graph APIs and cloud services, enabling data exfiltration through OneDrive, SharePoint, Teams, or any Microsoft Entra-integrated application in the external tenant. This attack path exploits the inherent trust that corporate networks and devices have with Microsoft identity services. Universal Tenant Restrictions address this by injecting tenant identity headers into authentication plane traffic via Global Secure Access, enabling Microsoft Entra ID to enforce tenant restrictions v2 policies that block authentication attempts to unauthorized external tenants. | ||
|
|
||
| **Remediation action** | ||
|
|
||
| Configure tenant restrictions v2 policies to block all external tenants by default | ||
| - [Set up tenant restrictions v2](https://learn.microsoft.com/en-us/entra/external-id/tenant-restrictions-v2) | ||
|
|
||
| Enable Universal Tenant Restrictions signaling in Global Secure Access | ||
| - [Turn on universal tenant restrictions](https://learn.microsoft.com/en-us/entra/global-secure-access/how-to-universal-tenant-restrictions) | ||
|
|
||
| Deploy Global Secure Access clients on devices | ||
| - [Global Secure Access clients overview](https://learn.microsoft.com/en-us/entra/global-secure-access/concept-clients) | ||
|
|
||
| Enable Microsoft traffic profile for Universal Tenant Restrictions | ||
| - [Microsoft traffic profile concept](https://learn.microsoft.com/en-us/entra/global-secure-access/concept-microsoft-traffic-profile) | ||
|
|
||
| **Who**: Global Secure Access Administrator (for Q1), Security Administrator or Global Administrator (for Q2) | ||
|
|
||
| **When**: During initial Global Secure Access deployment and before enabling production traffic forwarding | ||
|
|
||
| **Where**: Microsoft Entra admin center > Global Secure Access > Session Management > Universal Tenant Restrictions | ||
| <!--- Results ---> | ||
| %TestResult% | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| <# | ||
| .SYNOPSIS | ||
| Validates that Universal Tenant Restrictions (UTR) are configured to block access to unauthorized external tenants. | ||
|
|
||
| .DESCRIPTION | ||
| This test checks if Universal Tenant Restrictions are properly configured by verifying: | ||
| 1. Global Secure Access network packet tagging is enabled | ||
| 2. Tenant restrictions v2 default policy blocks all users and all applications | ||
|
|
||
| .NOTES | ||
| Test ID: 25377 | ||
| Category: Global Secure Access | ||
| Required API: networkAccess/settings/crossTenantAccess (beta), policies/crossTenantAccessPolicy/default (beta) | ||
| #> | ||
|
|
||
| function Test-Assessment-25377 { | ||
| [ZtTest( | ||
| Category = 'Global Secure Access', | ||
| ImplementationCost = 'Medium', | ||
| MinimumLicense = ('AAD_PREMIUM', 'Entra_Premium_Internet_Access'), | ||
| Pillar = 'Network', | ||
| RiskLevel = 'High', | ||
| SfiPillar = 'Protect networks', | ||
| TenantType = ('Workforce', 'External'), | ||
| TestId = 25377, | ||
| Title = 'Universal Tenant Restrictions block access to unauthorized external tenants', | ||
ashwinikarke marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| UserImpact = 'Low' | ||
| )] | ||
| [CmdletBinding()] | ||
| param() | ||
|
|
||
| #region Data Collection | ||
| Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose | ||
| $activity = 'Checking Universal Tenant Restrictions configuration' | ||
| Write-ZtProgress -Activity $activity -Status 'Querying Global Secure Access network packet tagging status' | ||
|
|
||
| # Q1: Get Global Secure Access Universal Tenant Restrictions status | ||
| try { | ||
| $crossTenantAccessSettings = Invoke-ZtGraphRequest -RelativeUri 'networkAccess/settings/crossTenantAccess' -ApiVersion beta -ErrorAction Stop | ||
| $networkPacketTaggingStatus = $crossTenantAccessSettings.networkPacketTaggingStatus | ||
| } | ||
| catch { | ||
| Write-PSFMessage "Failed to retrieve Global Secure Access cross-tenant access settings: $_" -Tag Test -Level Warning | ||
| $networkPacketTaggingStatus = $null | ||
| } | ||
|
|
||
| Write-ZtProgress -Activity $activity -Status 'Querying tenant restrictions v2 default policy' | ||
|
|
||
| # Q2: Get default cross-tenant access policy tenant restrictions configuration | ||
| try { | ||
| $defaultCrossTenantPolicy = Invoke-ZtGraphRequest -RelativeUri 'policies/crossTenantAccessPolicy/default' -ApiVersion beta -ErrorAction Stop | ||
| $tenantRestrictions = $defaultCrossTenantPolicy.tenantRestrictions | ||
| } | ||
| catch { | ||
| Write-PSFMessage "Failed to retrieve cross-tenant access policy: $_" -Tag Test -Level Warning | ||
| $tenantRestrictions = $null | ||
| } | ||
| #endregion Data Collection | ||
|
|
||
| #region Assessment Logic | ||
| $testResultMarkdown = '' | ||
| $passed = $false | ||
|
|
||
| # Check Q1: Network packet tagging must be enabled | ||
| if ($null -eq $networkPacketTaggingStatus -or $networkPacketTaggingStatus -ne 'enabled') { | ||
| $statusText = if ($null -eq $networkPacketTaggingStatus) { | ||
| 'not configured' | ||
| } | ||
| else { | ||
| $networkPacketTaggingStatus | ||
| } | ||
| $testResultMarkdown = "❌ Universal Tenant Restrictions are not fully configured. Network packet tagging is $statusText (expected: enabled). `n`n%TestResult%" | ||
| $passed = $false | ||
| } | ||
| else { | ||
| # Validate usersAndGroups configuration | ||
| $usersAndGroupsValid = $false | ||
| if ($tenantRestrictions.usersAndGroups) { | ||
| $usersAccessType = $tenantRestrictions.usersAndGroups.accessType | ||
ashwinikarke marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| $usersTargets = $tenantRestrictions.usersAndGroups.targets | ||
|
|
||
| # Check if accessType is blocked and targets contain AllUsers | ||
| if ($usersAccessType -eq 'blocked' -and $usersTargets) { | ||
| $hasAllUsers = $usersTargets | Where-Object { $_.target -eq 'AllUsers' } | ||
| $usersAndGroupsValid = $null -ne $hasAllUsers | ||
| } | ||
ashwinikarke marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| # Validate applications configuration | ||
| $applicationsValid = $false | ||
| if ($tenantRestrictions.applications) { | ||
| $appsAccessType = $tenantRestrictions.applications.accessType | ||
| $appsTargets = $tenantRestrictions.applications.targets | ||
|
|
||
| # Check if accessType is blocked and targets contain AllApplications | ||
| if ($appsAccessType -eq 'blocked' -and $appsTargets) { | ||
| $hasAllApplications = $appsTargets | Where-Object { $_.target -eq 'AllApplications' } | ||
| $applicationsValid = $null -ne $hasAllApplications | ||
| } | ||
ashwinikarke marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| # Both must be valid for test to pass | ||
| if ($usersAndGroupsValid -and $applicationsValid) { | ||
| $testResultMarkdown = "✅ Universal Tenant Restrictions are configured. Network packet tagging is enabled and the default tenant restrictions v2 policy blocks all users from accessing all applications in unauthorized external tenants. `n`n%TestResult%" | ||
| $passed = $true | ||
| } | ||
| else { | ||
| $testResultMarkdown = "❌ Universal Tenant Restrictions are not fully configured. Tenant restrictions v2 policy does not block all users and all applications by default. `n`n%TestResult%" | ||
| $passed = $false | ||
| } | ||
| } | ||
| #endregion Assessment Logic | ||
|
|
||
| #region Report Generation | ||
| # Calculate all values and status icons | ||
| # Network Packet Tagging | ||
| $networkPacketDisplay = if ($null -eq $networkPacketTaggingStatus) { 'Not configured' } else { $networkPacketTaggingStatus } | ||
| $networkPacketIcon = if ($networkPacketTaggingStatus -eq 'enabled') { '✅' } else { '❌' } | ||
|
|
||
| # Users & Groups Access Type | ||
| $usersAccessTypeDisplay = if ($tenantRestrictions.usersAndGroups) { $tenantRestrictions.usersAndGroups.accessType } else { 'Not configured' } | ||
| $usersAccessIcon = if ($usersAccessTypeDisplay -eq 'blocked') { '✅' } else { '❌' } | ||
|
|
||
| # Users & Groups Target - extract targets array properly | ||
| $usersTargetsArray = @() | ||
| if ($tenantRestrictions.usersAndGroups.targets) { | ||
| $usersTargetsArray = @($tenantRestrictions.usersAndGroups.targets | ForEach-Object { $_.target }) | ||
| } | ||
| $usersTargetDisplay = if ($usersTargetsArray.Count -gt 0) { $usersTargetsArray[0] } else { 'Not configured' } | ||
| $usersTargetIcon = if ($usersTargetsArray -contains 'AllUsers') { '✅' } else { '❌' } | ||
|
|
||
| # Applications Access Type | ||
| $appsAccessTypeDisplay = if ($tenantRestrictions.applications) { $tenantRestrictions.applications.accessType } else { 'Not configured' } | ||
| $appsAccessIcon = if ($appsAccessTypeDisplay -eq 'blocked') { '✅' } else { '❌' } | ||
|
|
||
| # Applications Target - extract targets array properly | ||
| $appsTargetsArray = @() | ||
| if ($tenantRestrictions.applications.targets) { | ||
| $appsTargetsArray = @($tenantRestrictions.applications.targets | ForEach-Object { $_.target }) | ||
| } | ||
| $appsTargetDisplay = if ($appsTargetsArray.Count -gt 0) { $appsTargetsArray[0] } else { 'Not configured' } | ||
| $appsTargetIcon = if ($appsTargetsArray -contains 'AllApplications') { '✅' } else { '❌' } | ||
|
|
||
| # Build configuration table using format template | ||
| $formatTemplate = @' | ||
|
|
||
| ## [{0}]({1}) | ||
|
|
||
| | Setting | Current Value | Expected Value | Status | | ||
| | :------ | :------------ | :------------- | :----: | | ||
| {2} | ||
|
|
||
| '@ | ||
|
|
||
| $reportTitle = 'Universal Tenant Restrictions Configuration' | ||
| $portalLink = 'https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantRestrictions.ReactView/isDefault~/true/name//id/' | ||
ashwinikarke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| $tableRows = "| Network Packet Tagging Status | $networkPacketDisplay | enabled | $networkPacketIcon |`n" | ||
| $tableRows += "| Users & Groups Access Type | $usersAccessTypeDisplay | blocked | $usersAccessIcon |`n" | ||
| $tableRows += "| Users & Groups Target | $usersTargetDisplay | AllUsers | $usersTargetIcon |`n" | ||
| $tableRows += "| Applications Access Type | $appsAccessTypeDisplay | blocked | $appsAccessIcon |`n" | ||
| $tableRows += "| Applications Target | $appsTargetDisplay | AllApplications | $appsTargetIcon |" | ||
|
|
||
| $mdInfo = $formatTemplate -f $reportTitle, $portalLink, $tableRows | ||
|
|
||
| # Replace the placeholder with detailed information | ||
| $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo | ||
| #endregion Report Generation | ||
|
|
||
| $params = @{ | ||
| TestId = '25377' | ||
| Title = 'Universal Tenant Restrictions block unauthorized external tenant access' | ||
ashwinikarke marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Status = $passed | ||
| Result = $testResultMarkdown | ||
| } | ||
|
|
||
| # Add test result details | ||
| Add-ZtTestResultDetail @params | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.