Workloads/Get-ConditionalAccessData.ps1
|
# Get-ConditionalAccessData.ps1 # Collects Conditional Access policies, named locations, and legacy auth signal. # Part of the M365-QuickAssess module -- not exported. function Get-ConditionalAccessData { param ( $Assessment ) Write-Log "Collecting Conditional Access data" # ------------------------------------------------------------------- # Policies and Named Locations # ------------------------------------------------------------------- try { $policies = Get-MgIdentityConditionalAccessPolicy -All -ErrorAction Stop $locations = Get-MgIdentityConditionalAccessNamedLocation -All -ErrorAction Stop # ------------------------------------------------------------------- # Policy Table -- flattened for the viewer # ------------------------------------------------------------------- $policyTable = @() foreach ( $p in $policies ) { $grantControls = if ( $p.GrantControls -and $p.GrantControls.BuiltInControls ) { $p.GrantControls.BuiltInControls -join ", " } else { "" } $clientApps = if ( $p.Conditions -and $p.Conditions.ClientAppTypes ) { $p.Conditions.ClientAppTypes -join ", " } else { "" } $users = if ( $p.Conditions -and $p.Conditions.Users -and $p.Conditions.Users.IncludeUsers ) { $p.Conditions.Users.IncludeUsers -join ", " } else { "" } $apps = if ( $p.Conditions -and $p.Conditions.Applications -and $p.Conditions.Applications.IncludeApplications ) { $p.Conditions.Applications.IncludeApplications -join ", " } else { "" } $policyTable += [ordered]@{ Name = $p.DisplayName State = $p.State Grant = $grantControls ClientApps = $clientApps Users = $users Apps = $apps } } # ------------------------------------------------------------------- # Summary Signals # ------------------------------------------------------------------- $hasMFA = ( $policies | Where-Object { $_.GrantControls -and $_.GrantControls.BuiltInControls -contains "mfa" } ).Count -gt 0 $hasTrustedLocations = ( $locations | Where-Object { $_.IsTrusted -eq $true } ).Count -gt 0 $Assessment.ConditionalAccess.HasConditionalAccessPolicies = ( $policies.Count -gt 0 ) $Assessment.ConditionalAccess.ConditionalAccessPolicyCount = $policies.Count $Assessment.ConditionalAccess.HasMFAEnforcement = $hasMFA $Assessment.ConditionalAccess.HasTrustedLocations = $hasTrustedLocations $Assessment.ConditionalAccess.Policies = $policyTable Write-Log "Conditional Access: Policies=$( $policies.Count ) MFA=$hasMFA TrustedLocations=$hasTrustedLocations" # ------------------------------------------------------------------- # Finding: No Conditional Access policies # ------------------------------------------------------------------- if ( $policies.Count -eq 0 ) { $Assessment.Findings += New-Finding ` -Type "NoConditionalAccessPolicies" ` -Summary "No Conditional Access policies detected" ` -Category "Security" ` -Severity "Medium" ` -Impact "No Entra Conditional Access policies are configured. This may be expected if the tenant uses a third-party identity provider such as Duo, Okta, or Ping for MFA and access control." ` -Recommendation "Confirm whether a third-party IdP is in use. If not, implement Conditional Access policies in the target tenant starting with MFA enforcement." } # ------------------------------------------------------------------- # Finding: No MFA enforcement via CA # ------------------------------------------------------------------- if ( $policies.Count -gt 0 -and -not $hasMFA ) { $Assessment.Findings += New-Finding ` -Type "NoMFAEnforcement" ` -Summary "No Conditional Access policy enforces MFA" ` -Category "Security" ` -Severity "Medium" ` -Impact "No Entra CA policy requiring MFA was detected. If MFA is enforced via a third-party IdP such as Duo or Okta this may be expected." ` -Recommendation "Confirm MFA enforcement method. If relying solely on Entra CA, create a policy requiring MFA for all users." } # ------------------------------------------------------------------- # Finding: Policies in report-only mode # ------------------------------------------------------------------- $reportOnlyCount = ( $policies | Where-Object { $_.State -eq "enabledForReportingButNotEnforced" } ).Count if ( $reportOnlyCount -gt 0 ) { $Assessment.Findings += New-Finding ` -Type "ReportOnlyCAPolices" ` -Summary "$reportOnlyCount Conditional Access policies are in report-only mode" ` -Category "Security" ` -Severity "Medium" ` -Impact "Report-only policies are not enforced and provide no protection." ` -Recommendation "Review report-only policies and enable them if appropriate." } } catch { Write-Log "Conditional Access collection failed: $( $_.Exception.Message )" "ERROR" } # ------------------------------------------------------------------- # Legacy Auth Signal # ------------------------------------------------------------------- try { Write-Log "Checking legacy authentication exposure" $legacyBlockPolicies = $policies | Where-Object { $_.Conditions -and $_.Conditions.ClientAppTypes -and ( $_.Conditions.ClientAppTypes -contains "exchangeActiveSync" -or $_.Conditions.ClientAppTypes -contains "other" ) } $hasLegacyBlock = ( $legacyBlockPolicies | Where-Object { $_.GrantControls -and $_.GrantControls.BuiltInControls -contains "block" } ).Count -gt 0 $Assessment.Summary.LegacyAuthEnabled = ( -not $hasLegacyBlock ) Write-Log "Legacy Auth Blocked: $hasLegacyBlock" # ------------------------------------------------------------------- # Finding: Legacy auth not blocked # ------------------------------------------------------------------- if ( -not $hasLegacyBlock ) { $Assessment.Findings += New-Finding ` -Type "LegacyAuthNotBlocked" ` -Summary "Legacy authentication protocols are not blocked" ` -Category "Security" ` -Severity "High" ` -Impact "Legacy auth protocols bypass MFA and are a common attack vector." ` -Recommendation "Create a Conditional Access policy to block legacy authentication for all users." } } catch { Write-Log "Legacy auth evaluation failed: $( $_.Exception.Message )" "WARN" } } |