Skip to content

Adding zero-trust assessments samples #1341

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions assets/aadconsentgrantpermissiontable.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Type,Permission,Privilege,Reason
Delegated,Mail.ReadBasic,Medium,DataExfiltration
Delegated,Mail,High,Phishing
Delegated,Contacts,High,Phishing
Delegated,MailboxSettings,High,Phishing
Delegated,People,High,Phishing
Delegated,Files,High,Phishing
Delegated,AllSites,High,Phishing
Delegated,Notes,High,Phishing
Delegated,Policy,High,Phishing
Delegated,AppRoleAssignment.ReadWrite.All,High,Phishing
Delegated,Directory.AccessAsUser.All,High,Phishing
Delegated,user_impersonation,High,Phishing
Delegated,Application.ReadWrite.All,High,BroadImpact
Delegated,Directory.ReadWrite.All,High,BroadImpact
Delegated,Domain.ReadWrite.All,High,BroadImpact
Delegated,EduRoster.ReadWrite.All,High,BroadImpact
Delegated,Group.ReadWrite.All,High,BroadImpact
Delegated,Member.Read.Hidden,High,BroadImpact
Delegated,RoleManagement.ReadWrite.Directory,High,BroadImpact
Delegated,RoleAssignmentSchedule.ReadWrite.Directory,High,BroadImpact
Delegated,RoleEligibilitySchedule.ReadWrite.Directory,High,BroadImpact
Delegated,User.ReadWrite.All,High,BroadImpact
Delegated,User.ManageCreds.All,High,BroadImpact
Delegated,User.Export.All,High,BroadImpact
Application,Mail,High,Phishing
Application,Contacts,High,Phishing
Application,MailboxSettings,High,Phishing
Application,People,High,Phishing
Application,Files,High,Phishing
Application,Sites,High,Phishing
Application,AllSites,High,Phishing
Application,Notes,High,Phishing
Application,Policy,High,BroadImpact
Application,PrivilegedAccess,High,BroadImpact
Application,PrivilegedAssignmentSchedule,High,BroadImpact
Application,PrivilegedEligibilitySchedule,High,BroadImpact
Application,AppRoleAssignment.ReadWrite.All,High,Phishing
Application,Directory.AccessAsUser.All,High,Phishing
Application,user_impersonation,High,Phishing
Application,Application.ReadWrite.All,High,BroadImpact
Application,Directory.ReadWrite.All,High,BroadImpact
Application,Domain.ReadWrite.All,High,BroadImpact
Application,EduRoster.ReadWrite.All,High,BroadImpact
Application,Group.ReadWrite.All,High,BroadImpact
Application,Member.Read.Hidden,High,BroadImpact
Application,UserAuthenticationMethod.ReadWrite.All,High,BroadImpact
Application,RoleManagement.ReadWrite.Directory,High,BroadImpact
Application,User.ReadWrite.All,High,BroadImpact
Application,User.ManageCreds.All,High,BroadImpact
Application,CallRecords.Read.All,High,SensitiveData
Delegated,User.Read,Low,Common pattern
Delegated,User.ReadBasic.All,Low,Common pattern
Delegated,openid,Low,Common pattern
Delegated,email,Low,Common pattern
Delegated,profile,Low,Common pattern
Delegated,offline_access,Low,Common pattern when used with other low permissions
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Connect to Entra with required scopes
Connect-Entra -Scopes 'AppRoleAssignment.ReadWrite.All', 'Application.ReadWrite.All', 'User.Read.All', 'Group.Read.All', 'DelegatedPermissionGrant.ReadWrite.All', 'AuditLog.Read.All'

# Define application name and redirect URI
$appName = "Entra PowerShell App (Application)"
$redirectUri = "http://localhost"

# Define Application permission and Graph API ID
$applicationPermission = 'Group.Read.All'
$graphApiId = '00000003-0000-0000-c000-000000000000'

# Get a user and a group
$user = Get-EntraUser -UserId 'AdeleV@contoso.com'
$group = Get-EntraGroup -Search 'Sales and Marketing'

# Create a new application
$app = New-EntraApplication -DisplayName $appName -PublicClient @{ RedirectUris = $redirectUri } -IsFallbackPublicClient $False

# Create a service principal for the application
$servicePrincipal = New-EntraServicePrincipal -AppId $app.AppId

# Assign users and groups to the application
$emptyGuidUser = [Guid]::Empty.ToString()
New-EntraUserAppRoleAssignment -ObjectId $user.Id -PrincipalId $user.Id -ResourceId $servicePrincipal.Id -Id $emptyGuidUser

$emptyGuidGroup = [Guid]::Empty.ToString()
New-EntraGroupAppRoleAssignment -GroupId $group.Id -PrincipalId $group.Id -ResourceId $servicePrincipal.Id -Id $emptyGuidGroup

# Get Graph service principal
$graphServicePrincipal = Get-EntraServicePrincipal -Filter "AppId eq '$graphApiId'"

# Create resource access object
$resourceAccessAppPerms = New-Object Microsoft.Open.MSGraph.Model.ResourceAccess
$resourceAccessAppPerms.Id = ((Get-EntraServicePrincipal -ServicePrincipalId $graphServicePrincipal.ObjectId).AppRoles | Where-Object { $_.Value -eq $applicationPermission}).Id
$resourceAccessAppPerms.Type = 'Scope'

# Create required resource access object
$requiredResourceAccessAppPerms = New-Object Microsoft.Open.MSGraph.Model.RequiredResourceAccess
$requiredResourceAccessAppPerms.ResourceAppId = $graphApiId
$requiredResourceAccessAppPerms.ResourceAccess = $resourceAccessAppPerms

# Set application required resource access
Set-EntraApplication -ApplicationId $app.Id -RequiredResourceAccess $requiredResourceAccessAppPerms

# Set service principal parameters
Set-EntraServicePrincipal -ServicePrincipalId $servicePrincipal.Id -AppRoleAssignmentRequired $True

# Get application role ID
$appRoleId = ($graphServicePrincipal.AppRoles | Where-Object { $_.Value -eq $applicationPermission }).Id

New-EntraServicePrincipalAppRoleAssignment -ObjectId $servicePrincipal.Id -ResourceId $graphServicePrincipal.Id -Id $appRoleId -PrincipalId $servicePrincipal.Id
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Connect to Entra with required scopes
Connect-Entra -Scopes 'AppRoleAssignment.ReadWrite.All', 'Application.ReadWrite.All', 'User.Read.All', 'Group.Read.All', 'DelegatedPermissionGrant.ReadWrite.All', 'AuditLog.Read.All'

# Define application name and redirect URI
$appName = "Entra PowerShell App (Delegated)"
$redirectUri = "http://localhost"

# Define delegated permission and Graph API ID
$delegatedPermission = 'User.Read.All'
$graphApiId = '00000003-0000-0000-c000-000000000000'

# Get a user and a group
$user = Get-EntraUser -UserId 'AdeleV@contoso.com'
$group = Get-EntraGroup -Search 'Sales and Marketing'

# Create a new application
$app = New-EntraApplication -DisplayName $appName -PublicClient @{ RedirectUris = $redirectUri } -IsFallbackPublicClient $False

# Create a service principal for the application
$servicePrincipal = New-EntraServicePrincipal -AppId $app.AppId

# Assign users and groups to the application
$emptyGuidUser = [Guid]::Empty.ToString()
New-EntraUserAppRoleAssignment -ObjectId $user.Id -PrincipalId $user.Id -ResourceId $servicePrincipal.Id -Id $emptyGuidUser

$emptyGuidGroup = [Guid]::Empty.ToString()
New-EntraGroupAppRoleAssignment -GroupId $group.Id -PrincipalId $group.Id -ResourceId $servicePrincipal.Id -Id $emptyGuidGroup

# Get Graph service principal
$graphServicePrincipal = Get-EntraServicePrincipal -Filter "AppId eq '$graphApiId'"

# Create resource access object
$resourceAccessDelegated = New-Object Microsoft.Open.MSGraph.Model.ResourceAccess
$resourceAccessDelegated.Id = ((Get-EntraServicePrincipal -ServicePrincipalId $graphServicePrincipal.Id).Oauth2PermissionScopes | Where-Object { $_.Value -eq $delegatedPermission }).Id
$resourceAccessDelegated.Type = 'Scope'

# Create required resource access object
$requiredResourceAccessDelegated = New-Object Microsoft.Open.MSGraph.Model.RequiredResourceAccess
$requiredResourceAccessDelegated.ResourceAppId = $graphApiId
$requiredResourceAccessDelegated.ResourceAccess = $resourceAccessDelegated

# Set application required resource access
Set-EntraApplication -ApplicationId $app.Id -RequiredResourceAccess $requiredResourceAccessDelegated

# Set service principal parameters
Set-EntraServicePrincipal -ServicePrincipalId $servicePrincipal.Id -AppRoleAssignmentRequired $True

# Grant OAuth2 permission
$permissionGrant = New-EntraOauth2PermissionGrant -ClientId $servicePrincipal.Id -ConsentType 'AllPrincipals' -ResourceId $graphServicePrincipal.Id -Scope $delegatedPermission

# Get and filter OAuth2 permission grants
Get-EntraOAuth2PermissionGrant -All | Where-Object { $_.Id -eq $permissionGrant.Id }
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<#
DISCLAIMER: This script is not an official PowerShell script and is specifically designed for the current situation you are facing.
It is provided "AS IS" with no warranties of any kind, either express or implied, including, but not limited to, any implied warranties of merchantability or fitness for a particular purpose.
This script is not supported by any official Microsoft support programs or services. Microsoft disclaims all implied warranties, including but not limited to implied warranties of merchantability or fitness for a particular purpose.
You assume all risk related to the use or performance of this script and its associated documentation. Under no circumstances shall Microsoft, its authors, or any other party involved in the creation, production, or delivery of this script be liable for any damages (including, but not limited to, loss of business profits, business interruptions, loss of business information, or other financial losses) arising from the use or inability to use the script or documentation, even if Microsoft has been advised of the possibility of such damages.

This script requires Microsoft Graph v1.0, as its logic depends on specific property values from this version. It is only compatible with Microsoft Graph PowerShell v2.x.x, which ensures that Microsoft Graph v1.0 is used. If you are using Microsoft Graph PowerShell v1, please upgrade to v2.
For more information, visit: https://devblogs.microsoft.com/microsoft365dev/microsoft-graph-powershell-v2-is-now-in-public-preview-half-the-size-and-will-speed-up-your-automations/

Ensure you have the appropriate privileges when running this script, such as `Global Reader` or `Identity Governance Administrator`.
#>
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Identity.Governance

# Connect to Microsoft Graph with the required scopes
Connect-MgGraph -Scopes EntitlementManagement.Read.All

# Define allowed target scopes
$allowedTargetScopes = @("allExternalUsers","allConfiguredConnectedOrganizationUsers","specificConnectedOrganizationUsers")
$PoliciesToReview = @()

Write-Host "Starting to search for policies..."
try{
$Policies = Get-MgEntitlementManagementAssignmentPolicy -Property Id,DisplayName,AllowedTargetScope,RequestApprovalSettings -All -Top 999
Write-Host "Successfully imported $($Policies.Count) policies"
}catch{
Write-Error "Error importing policies: $_"
return
}

Write-Host "Starting to analyze policies"
foreach($Policy in $Policies){
if($allowedTargetScopes -contains $Policy.AllowedTargetScope){
if($Policy.RequestApprovalSettings.IsApprovalRequiredForAdd -ne $true){
try {
$PolicyDetails = Get-MgEntitlementManagementAssignmentPolicy -AccessPackageAssignmentPolicyId $Policy.Id -ExpandProperty accessPackage,catalog
$PoliciesToReview += $PolicyDetails
}
catch {
Write-Error "Error getting policy details: $_"
return
}

}
}
}

Write-Host "Analysis completed we have identified $($PoliciesToReview.Count) policies which should be reviewed:"
Write-Host ($PoliciesToReview | Format-Table | Out-String)

Write-Host "Access packages associated with these policies:"
Write-Host ($PoliciesToReview.AccessPackage | Format-Table | Out-String)

Write-Host "Script completed. More information can be found in the `$PoliciesToReview variable."
File renamed without changes.
27 changes: 27 additions & 0 deletions samples/zero-trust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: Zero Trust Scenarios
description: Zero Trust scenarios.

ms.service: microsoft-entra-powershell
ms.topic: reference
ms.date: 02/03/2025
ms.author: eunicewaweru
ms.reviewer: stevemutungi
manager: CelesteDG
author: msewaweru
---

# Zero Trust Scenarios

This section explains how scenario assessments can reduce the attack surface and limit the impact of breaches.

| Scenario | Rationale |
| -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Inactive applications shouldn't have highly privileged Microsoft Graph API permissions](./get-inactive-apps-with-high-priv-permissions.ps1) | Attackers can exploit inactive yet privileged applications to gain initial access and execute further attacks without detection. They may also manipulate these applications, such as by adding credentials, to maintain persistent access even if their primary method is discovered |
| Scenario 2 | Description of scenario 2 |
| Scenario 3 | Description of scenario 3 |
| Scenario 4 | Description of scenario 4 |
| Scenario 4 | Description of scenario 4 |
| Scenario 4 | Description of scenario 4 |
| Scenario 4 | Description of scenario 4 |
| Scenario 4 | Description of scenario 4 |
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# ------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All Rights Reserved.
# Licensed under the MIT License. See License in the project root for license information.
# ------------------------------------------------------------------------------

# Connect to Microsoft Graph with necessary permissions
Connect-Entra -Scopes "Application.Read.All", "Directory.Read.All", "AuditLog.Read.All" -NoWelcome

# Define inactivity threshold (e.g., 90 days)
$inactiveThreshold = (Get-Date).AddDays(-90)

# Sample list of highly privileged Microsoft Graph API permissions
$highPrivPermissions = @(
"Directory.ReadWrite.All",
"Directory.AccessAsUser.All",
"User.ReadWrite.All",
"Group.ReadWrite.All",
"Application.ReadWrite.All",
"RoleManagement.ReadWrite.Directory",
"Policy.ReadWrite.ConditionalAccess",
"Device.ReadWrite.All"
)

# Get Microsoft Graph Service Principal - Note: You can also use the AppId ""00000003-0000-0000-c000-000000000000"" instead of the DisplayName
$msGraphServicePrincipal = Get-EntraServicePrincipal -Filter "displayName eq 'Microsoft Graph'"

# Map permission IDs to friendly names
$highPrivPermIds = @{}

foreach ($role in $msGraphServicePrincipal.AppRoles) {
if ($highPrivPermissions -contains $role.Value) {
$highPrivPermIds[$role.Id] = $role.Value
}
}

foreach ($scope in $msGraphServicePrincipal.OAuth2PermissionScopes) {
if ($highPrivPermissions -contains $scope.Value) {
$highPrivPermIds[$scope.Id] = $scope.Value
}
}

# Retrieve all registered applications
$applications = Get-EntraApplication -All
$appsWithHighPriv = @()

foreach ($app in $applications) {
$hasHighPriv = $false
$appHighPrivPermissions = @()
if ($app.RequiredResourceAccess) {
foreach ($req in $app.RequiredResourceAccess) {
if ($req.ResourceAppId -eq $msGraphServicePrincipal.AppId) {
foreach ($perm in $req.ResourceAccess) {
if ($highPrivPermIds.ContainsKey($perm.Id)) {
$hasHighPriv = $true
$appHighPrivPermissions += $highPrivPermIds[$perm.Id]
}
}
}
if ($hasHighPriv) { break }
}
}
if ($hasHighPriv) {
$app | Add-Member -MemberType NoteProperty -Name HighPrivilegedPermissions -Value $appHighPrivPermissions
$appsWithHighPriv += $app
}
}

# Check inactivity based on sign-in activity
$inactiveApps = @()

foreach ($app in $appsWithHighPriv) {
$sp = Get-EntraServicePrincipal -Filter "appId eq '$($app.AppId)'" -ErrorAction SilentlyContinue
$lastSignIn = $null

if ($sp -and $sp.SignInActivity) {
$lastSignIn = $sp.SignInActivity.LastSignInDateTime
}

# Mark as inactive if never signed in or last sign-in is older than threshold
$isInactive = -not $lastSignIn -or ([datetime]$lastSignIn -lt $inactiveThreshold)

if ($isInactive) {
$inactiveApps += [PSCustomObject]@{
ApplicationName = $app.DisplayName
AppId = $app.AppId
LastSignIn = $lastSignIn
HighPrivilegedPermissions = $app.HighPrivilegedPermissions -join ", "
}
}
}

$inactiveApps | Format-Table -AutoSize