SHELL/helpers/ca_policy_helpers.ps1
|
function Get-Root365Value { param( [AllowNull()][object]$Object, [Parameter(Mandatory = $true)][string]$Name ) if ($null -eq $Object) { return $null } if ($Object -is [System.Collections.IDictionary]) { foreach ($Key in $Object.Keys) { if ([string]$Key -ieq $Name) { return $Object[$Key] } } } if ($Object.PSObject -and $Object.PSObject.Properties) { foreach ($Property in $Object.PSObject.Properties) { if ([string]$Property.Name -ieq $Name) { return $Property.Value } } } return $null } function Get-Root365PathValue { param( [AllowNull()][object]$Object, [Parameter(Mandatory = $true)][string[]]$Path ) $Current = $Object foreach ($Segment in $Path) { if ($null -eq $Current) { return $null } $Current = Get-Root365Value -Object $Current -Name $Segment } return $Current } function Convert-Root365StringArray { param([AllowNull()]$Value) if ($null -eq $Value) { return @() } $Items = @() if ($Value -is [string]) { $Items = @($Value) } elseif ($Value -is [System.Collections.IEnumerable] -and -not ($Value -is [string])) { $Items = @($Value) } else { $Items = @($Value) } $Result = foreach ($Item in $Items) { if ($null -eq $Item) { continue } $Text = [string]$Item if (-not [string]::IsNullOrWhiteSpace($Text)) { $Text.Trim() } } return @($Result | Where-Object { $_ } | Select-Object -Unique) } function Convert-Root365NullableBool { param([AllowNull()]$Value) if ($null -eq $Value) { return $null } if ($Value -is [bool]) { return [bool]$Value } $Text = ([string]$Value).Trim() if ($Text -match '^(?i:true|1|yes|enabled)$') { return $true } if ($Text -match '^(?i:false|0|no|disabled)$') { return $false } return $null } function Get-Root365CaPoliciesRaw { if (-not (Get-Command -Name Invoke-MgGraphRequest -ErrorAction SilentlyContinue)) { throw "Invoke-MgGraphRequest cmdlet is unavailable in the current session." } $Uri = 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies?$top=500' $Policies = [System.Collections.Generic.List[object]]::new() while (-not [string]::IsNullOrWhiteSpace($Uri)) { $Response = Invoke-MgGraphRequest -Uri $Uri -Method GET -ErrorAction Stop $Values = @(Get-Root365Value -Object $Response -Name 'value') foreach ($Policy in $Values) { $Policies.Add($Policy) } $Uri = [string](Get-Root365Value -Object $Response -Name '@odata.nextLink') } return @($Policies) } function Get-Root365CaPoliciesNormalized { $Policies = @(Get-Root365CaPoliciesRaw) $Normalized = [System.Collections.Generic.List[object]]::new() foreach ($Policy in $Policies) { $Users = Get-Root365PathValue -Object $Policy -Path @('conditions', 'users') $Applications = Get-Root365PathValue -Object $Policy -Path @('conditions', 'applications') $GrantControls = Get-Root365PathValue -Object $Policy -Path @('grantControls') $SessionControls = Get-Root365PathValue -Object $Policy -Path @('sessionControls') $SignInFrequency = Get-Root365PathValue -Object $SessionControls -Path @('signInFrequency') $PersistentBrowser = Get-Root365PathValue -Object $SessionControls -Path @('persistentBrowser') $State = [string](Get-Root365Value -Object $Policy -Name 'state') $Normalized.Add([pscustomobject]@{ Id = [string](Get-Root365Value -Object $Policy -Name 'id') DisplayName = [string](Get-Root365Value -Object $Policy -Name 'displayName') State = $State IsEnabled = ($State -eq 'enabled') IncludeUsers = Convert-Root365StringArray -Value (Get-Root365Value -Object $Users -Name 'includeUsers') ExcludeUsers = Convert-Root365StringArray -Value (Get-Root365Value -Object $Users -Name 'excludeUsers') IncludeRoles = Convert-Root365StringArray -Value (Get-Root365Value -Object $Users -Name 'includeRoles') ExcludeRoles = Convert-Root365StringArray -Value (Get-Root365Value -Object $Users -Name 'excludeRoles') IncludeGroups = Convert-Root365StringArray -Value (Get-Root365Value -Object $Users -Name 'includeGroups') ExcludeGroups = Convert-Root365StringArray -Value (Get-Root365Value -Object $Users -Name 'excludeGroups') IncludeApplications = Convert-Root365StringArray -Value (Get-Root365Value -Object $Applications -Name 'includeApplications') ExcludeApplications = Convert-Root365StringArray -Value (Get-Root365Value -Object $Applications -Name 'excludeApplications') IncludeUserActions = Convert-Root365StringArray -Value (Get-Root365Value -Object $Applications -Name 'includeUserActions') ClientAppTypes = Convert-Root365StringArray -Value (Get-Root365PathValue -Object $Policy -Path @('conditions', 'clientAppTypes')) UserRiskLevels = Convert-Root365StringArray -Value (Get-Root365PathValue -Object $Policy -Path @('conditions', 'userRiskLevels')) SignInRiskLevels = Convert-Root365StringArray -Value (Get-Root365PathValue -Object $Policy -Path @('conditions', 'signInRiskLevels')) AuthenticationFlowTransferMethods = Convert-Root365StringArray -Value (Get-Root365PathValue -Object $Policy -Path @('conditions', 'authenticationFlows', 'transferMethods')) GrantBuiltInControls = Convert-Root365StringArray -Value (Get-Root365Value -Object $GrantControls -Name 'builtInControls') GrantOperator = [string](Get-Root365Value -Object $GrantControls -Name 'operator') AuthenticationStrengthId = [string](Get-Root365PathValue -Object $GrantControls -Path @('authenticationStrength', 'id')) AuthenticationStrengthDisplayName = [string](Get-Root365PathValue -Object $GrantControls -Path @('authenticationStrength', 'displayName')) SignInFrequencyEnabled = Convert-Root365NullableBool -Value (Get-Root365Value -Object $SignInFrequency -Name 'isEnabled') SignInFrequencyValue = Get-Root365Value -Object $SignInFrequency -Name 'value' SignInFrequencyType = [string](Get-Root365Value -Object $SignInFrequency -Name 'type') SignInFrequencyInterval = [string](Get-Root365Value -Object $SignInFrequency -Name 'frequencyInterval') PersistentBrowserEnabled = Convert-Root365NullableBool -Value (Get-Root365Value -Object $PersistentBrowser -Name 'isEnabled') PersistentBrowserMode = [string](Get-Root365Value -Object $PersistentBrowser -Name 'mode') }) } return @($Normalized) } function Test-Root365ContainsValue { param( [AllowNull()]$Collection, [Parameter(Mandatory = $true)][string]$Expected ) foreach ($Item in @(Convert-Root365StringArray -Value $Collection)) { if ([string]$Item -ieq $Expected) { return $true } } return $false } function Test-Root365ContainsAllValues { param( [AllowNull()]$Collection, [string[]]$ExpectedValues ) foreach ($Expected in @($ExpectedValues)) { if (-not (Test-Root365ContainsValue -Collection $Collection -Expected $Expected)) { return $false } } return $true } function Convert-Root365SignInFrequencyToHours { param( [AllowNull()]$Value, [string]$Type ) if ($null -eq $Value) { return $null } $Numeric = 0.0 if (-not [double]::TryParse(([string]$Value), [ref]$Numeric)) { return $null } switch (($Type | ForEach-Object { $_.ToLowerInvariant() })) { 'hours' { return $Numeric } 'days' { return ($Numeric * 24) } default { return $null } } } function Test-Root365SignInFrequencyEveryTime { param([Parameter(Mandatory = $true)][object]$Policy) if ($Policy.SignInFrequencyEnabled -ne $true) { return $false } if (($Policy.SignInFrequencyInterval | ForEach-Object { $_.ToLowerInvariant() }) -eq 'everytime') { return $true } $Hours = Convert-Root365SignInFrequencyToHours -Value $Policy.SignInFrequencyValue -Type $Policy.SignInFrequencyType if ($null -ne $Hours -and $Hours -le 1) { return $true } return $false } function Get-Root365CaPolicyEvidenceSummary { param([AllowNull()]$Policies) return @( @($Policies) | Select-Object Id, DisplayName, State, IncludeUsers, ExcludeUsers, IncludeRoles, ExcludeRoles, IncludeApplications, ExcludeApplications, IncludeUserActions, ClientAppTypes, UserRiskLevels, SignInRiskLevels, AuthenticationFlowTransferMethods, GrantBuiltInControls, GrantOperator, AuthenticationStrengthDisplayName, SignInFrequencyEnabled, SignInFrequencyValue, SignInFrequencyType, SignInFrequencyInterval, PersistentBrowserEnabled, PersistentBrowserMode ) } |