diff --git a/powershell/public/Test-MtConditionalAccessWhatIf.ps1 b/powershell/public/Test-MtConditionalAccessWhatIf.ps1 index 99836e72..e99565e9 100644 --- a/powershell/public/Test-MtConditionalAccessWhatIf.ps1 +++ b/powershell/public/Test-MtConditionalAccessWhatIf.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS Tests Conditional Access evaluation with What If for a given scenario. @@ -9,41 +9,50 @@ Learn more: https://learn.microsoft.com/entra/identity/conditional-access/what-if-tool + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/test-mgbetaidentityconditionalaccess?view=graph-powershell-beta .EXAMPLE - Test-MtConditionalAccessWhatIf -UserId 7a6da1c3-616a-416b-a820-cbe4fa8e225e ` - -IncludeApplications "00000002-0000-0ff1-ce00-000000000000" ` - -ClientAppType exchangeActiveSync + Test-MtConditionalAccessWhatIf -UserId '7a6da1c3-616a-416b-a820-cbe4fa8e225e' ` + -IncludeApplications '00000002-0000-0ff1-ce00-000000000000' ` + -ClientAppType 'exchangeActiveSync' This example tests the Conditional Access policies for a user signing into Exchange Online using a legacy Mail client that relies on basic authentication. .EXAMPLE - Test-MtConditionalAccessWhatIf -UserId 7a6da1c3-616a-416b-a820-cbe4fa8e225e ` - -UserAction registerOrJoinDevices + Test-MtConditionalAccessWhatIf -UserId '7a6da1c3-616a-416b-a820-cbe4fa8e225e' ` + -UserAction 'registerOrJoinDevices' This example tests the Conditional Access policies for a user registering or joining a device to Microsoft Entra. .EXAMPLE - Test-MtConditionalAccessWhatIf -UserId 7a6da1c3-616a-416b-a820-cbe4fa8e225e ` + Test-MtConditionalAccessWhatIf -UserId '7a6da1c3-616a-416b-a820-cbe4fa8e225e' ` -IncludeApplications '67ad5377-2d78-4ac2-a867-6300cda00e85' ` - -Country FR -IpAddress '92.205.185.202' + -Country 'FR' -IpAddress '92.205.185.202' This example tests the Conditional Access policies for a user signing into **Office 365** from **France** with a specific **IP address**. .EXAMPLE - Test-MtConditionalAccessWhatIf -UserId 7a6da1c3-616a-416b-a820-cbe4fa8e225e ` + Test-MtConditionalAccessWhatIf -UserId '7a6da1c3-616a-416b-a820-cbe4fa8e225e' ` -IncludeApplications '67ad5377-2d78-4ac2-a867-6300cda00e85' ` - -SignInRiskLevel High -DevicePlatform iOS + -SignInRiskLevel 'High' -DevicePlatform 'iOS' This example tests the Conditional Access policies for a user signing into **Office 365** from an **iOS** device with a **High** sign-in risk level. .EXAMPLE - Test-MtConditionalAccessWhatIf -UserId 7a6da1c3-616a-416b-a820-cbe4fa8e225e ` - -UserAction registerSecurityInformation ` - -DevicePlatform Android ` - -UserRiskLevel High + Test-MtConditionalAccessWhatIf -UserId '7a6da1c3-616a-416b-a820-cbe4fa8e225e' ` + -IncludeApplications 'bbad9299-f060-4e15-9a9a-285980ae00fc' ` + -DeviceInfo { 'isCompliant' = 'true'; 'Manufacturer' = 'Dell' } ` + -InsiderRiskLevel 'Minor' - This example tests the Conditional Access policies for a user accessing the **My Security Info** page from an **Android** device with a **High** user risk level. + This example tests the Conditional Access policies for a user accessing an **application** from a **compliant**, **Dell** device with a **Minor** insider risk level. + +.EXAMPLE + Test-MtConditionalAccessWhatIf -UserId '7a6da1c3-616a-416b-a820-cbe4fa8e225e' ` + -IncludeApplications 'a7936c39-024c-4148-a9b3-f88f2e9406f6' ` + -ServicePrincipalRiskLevel 'High' -Verbose -IncludeReportOnly -IncludeDisabled -PrettyJsonVerboseOutput + + This example tests the Conditional Access policies for a service principal user accessing the **application** with a **High** service principal risk level. + It will return all applied results, including the report-only and disabled policies. It will print the Graph API input and output JSON objects in a pretty format. .LINK https://maester.dev/docs/commands/Test-MtConditionalAccessWhatIf @@ -96,6 +105,55 @@ function Test-MtConditionalAccessWhatIf { [ValidateSet("None", "Low", "Medium", "High")] [string]$UserRiskLevel, + # Insider risk level for the test. + # Values can be Minor, Moderate, Elevated + [Parameter(ValueFromPipelineByPropertyName = $true)] + [ValidateSet("Minor", "Moderate", "Elevated")] + [string]$InsiderRiskLevel, + + # Service Principal risk level for the test. + # Values can be None, Low, Medium, High + [Parameter(ValueFromPipelineByPropertyName = $true)] + [ValidateSet("None", "Low", "Medium", "High")] + [string]$ServicePrincipalRiskLevel, + + # Device info to be used for the test. + # Values can be any key-value pair + + #[DeviceInfo ]: deviceInfo + # [(Any) ]: This indicates any property can be added to this object. + # [DeviceId ]: + # [DisplayName ]: + # [EnrollmentProfileName ]: + # [ExtensionAttribute1 ]: + # [ExtensionAttribute10 ]: + # [ExtensionAttribute11 ]: + # [ExtensionAttribute12 ]: + # [ExtensionAttribute13 ]: + # [ExtensionAttribute14 ]: + # [ExtensionAttribute15 ]: + # [ExtensionAttribute2 ]: + # [ExtensionAttribute3 ]: + # [ExtensionAttribute4 ]: + # [ExtensionAttribute5 ]: + # [ExtensionAttribute6 ]: + # [ExtensionAttribute7 ]: + # [ExtensionAttribute8 ]: + # [ExtensionAttribute9 ]: + # [IsCompliant ]: + # [Manufacturer ]: + # [MdmAppId ]: + # [Model ]: + # [OperatingSystem ]: + # [OperatingSystemVersion ]: + # [Ownership ]: + # [PhysicalIds ]: + # [ProfileType ]: + # [SystemLabels ]: + # [TrustType ]: + [Parameter(ValueFromPipelineByPropertyName = $true)] + [hashtable]$DeviceInfo, + # Country to be used for the test. The two-letter country code. [Parameter(ValueFromPipelineByPropertyName = $true)] [ValidateSet("AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW")] @@ -106,9 +164,24 @@ function Test-MtConditionalAccessWhatIf { [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$IpAddress, - # Output all results - [Parameter()] - [switch]$AllResults + # Output all results, not only the applied policies. + [Parameter(ValueFromPipelineByPropertyName = $true)] + [switch]$AllResults, + + # IncludeReportOnly + # Include report-only policies in the final resultset + [Parameter(ValueFromPipelineByPropertyName = $true)] + [switch]$IncludeReportOnly, + + # IncludeDisabled + # Include disabled policies in the final resultset + [Parameter(ValueFromPipelineByPropertyName = $true)] + [switch]$IncludeDisabled, + + # Pretty JSON verbose output + # Pretty print Whatif input and result JSON objects in verbose mode + [Parameter(ValueFromPipelineByPropertyName = $true)] + [switch]$PrettyJsonVerboseOutput ) process { @@ -132,7 +205,8 @@ function Test-MtConditionalAccessWhatIf { } } - $ConditionalAccessWhatIfDefinition = @{ + $ConditionalAccessWhatIfBodyParameter = @{ + "AppliedPoliciesOnly" = -not $AllResults "conditionalAccessWhatIfSubject" = @{ "@odata.type" = "#microsoft.graph.userSubject" "userId" = $UserId @@ -141,27 +215,33 @@ function Test-MtConditionalAccessWhatIf { "conditionalAccessWhatIfConditions" = @{} } - $whatIfConditions = $ConditionalAccessWhatIfDefinition.conditionalAccessWhatIfConditions + $whatIfConditions = $ConditionalAccessWhatIfBodyParameter.conditionalAccessWhatIfConditions if ($UserRiskLevel) { $whatIfConditions.userRiskLevel = $UserRiskLevel } + if ($InsiderRiskLevel) { $whatIfConditions.insiderRiskLevel = $InsiderRiskLevel } + if ($ServicePrincipalRiskLevel) { $whatIfConditions.servicePrincipalRiskLevel = $ServicePrincipalRiskLevel } if ($SignInRiskLevel) { $whatIfConditions.signInRiskLevel = $SignInRiskLevel } if ($ClientAppType) { $whatIfConditions.clientAppType = $ClientAppType } if ($DevicePlatform) { $whatIfConditions.devicePlatform = $DevicePlatform } + if ($DeviceInfo) { $whatIfConditions.deviceInfo = $DeviceInfo } if ($Country) { $whatIfConditions.country = $Country } if ($IpAddress) { $whatIfConditions.ipAddress = $IpAddress } - Write-Verbose ( $ConditionalAccessWhatIfDefinition | ConvertTo-Json -Depth 99 -Compress ) + Write-Verbose "ConditionalAccessWhatIfBodyParameter: $( $ConditionalAccessWhatIfBodyParameter | ConvertTo-Json -Depth 99 -Compress:($PrettyJsonVerboseOutput -eq $false) )" try { - $ConditionalAccessWhatIfResult = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/beta/identity/conditionalAccess/evaluate" -OutputType PSObject -Body ( $ConditionalAccessWhatIfDefinition | ConvertTo-Json -Depth 99 -Compress ) | Select-Object -ExpandProperty value - # Filter out policies that do not apply - if (!$AllResults) { - $ConditionalAccessWhatIfResult = $ConditionalAccessWhatIfResult | Where-Object { $_.policyApplies -eq $true } - } + $ConditionalAccessWhatIfResult = Test-MgBetaIdentityConditionalAccess -BodyParameter $ConditionalAccessWhatIfBodyParameter + + $returnStates = @('enabled') + $returnStates += @('enabledForReportingButNotEnforced') * [bool]$IncludeReportOnly + $returnStates += @('disabled') * [bool]$IncludeDisabled + Write-Verbose "Including policies in result set with states: $returnStates" + + $ConditionalAccessWhatIfResult = ($ConditionalAccessWhatIfResult | Where-Object { $_.state -in $returnStates }) + Write-Verbose "ConditionalAccessWhatIfResult: $( $ConditionalAccessWhatIfResult | ConvertTo-Json -Depth 99 -Compress:($PrettyJsonVerboseOutput -eq $false) )" return $ConditionalAccessWhatIfResult } catch { Write-Error $_.Exception.Message } } } -