Private/Entra/Checks/Invoke-M365PowerPlatformChecks.ps1
|
# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0 # https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/ # AI/LLM use: see AI-USAGE.md for required attribution function Invoke-M365PowerPlatformChecks { [CmdletBinding()] param( [Parameter(Mandatory)] [hashtable]$AuditData ) $checkDefs = Get-AuditCategoryDefinitions -Category 'M365PowerPlatformChecks' $findings = [System.Collections.Generic.List[PSCustomObject]]::new() foreach ($check in $checkDefs.checks) { $funcName = "Test-Infiltration$($check.id -replace '-', '')" if (Get-Command $funcName -ErrorAction SilentlyContinue) { try { $finding = & $funcName -AuditData $AuditData -CheckDefinition $check if ($finding) { $findings.Add($finding) } } catch { $findings.Add((New-AuditFinding -CheckDefinition $check -Status 'ERROR' ` -CurrentValue "Check failed: $_")) } } else { $findings.Add((New-AuditFinding -CheckDefinition $check -Status 'SKIP' ` -CurrentValue 'Check not yet implemented')) } } return @($findings) } # ── M365PP-001: Environment Creation Restrictions ──────────────────── function Test-InfiltrationM365PP001 { [CmdletBinding()] param([hashtable]$AuditData, [hashtable]$CheckDefinition) $pp = $AuditData.M365Services.PowerPlatform if (-not $pp) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'SKIP' ` -CurrentValue 'Power Platform data not available (Power Platform admin module not connected)' } $envCreationRestricted = $pp.EnvironmentCreationRestricted $disableEnvironmentCreationByNonAdminUsers = $pp.DisableEnvironmentCreationByNonAdminUsers # Check either property depending on data source $restricted = $envCreationRestricted -eq $true -or $disableEnvironmentCreationByNonAdminUsers -eq $true if ($null -eq $envCreationRestricted -and $null -eq $disableEnvironmentCreationByNonAdminUsers) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'SKIP' ` -CurrentValue 'Environment creation restriction settings not available' } $status = if ($restricted) { 'PASS' } else { 'FAIL' } $description = if ($restricted) { 'Environment creation is restricted to administrators only' } else { 'Any user can create Power Platform environments — restrict to admins to prevent sprawl' } return New-AuditFinding -CheckDefinition $CheckDefinition -Status $status ` -CurrentValue $description ` -Details @{ EnvironmentCreationRestricted = $envCreationRestricted DisableEnvironmentCreationByNonAdminUsers = $disableEnvironmentCreationByNonAdminUsers } } # ── M365PP-002: DLP Policies for Connectors ────────────────────────── function Test-InfiltrationM365PP002 { [CmdletBinding()] param([hashtable]$AuditData, [hashtable]$CheckDefinition) $pp = $AuditData.M365Services.PowerPlatform if (-not $pp) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'SKIP' ` -CurrentValue 'Power Platform data not available (Power Platform admin module not connected)' } $dlpPolicies = $pp.DlpPolicies if ($null -eq $dlpPolicies) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'SKIP' ` -CurrentValue 'Power Platform DLP policy data not available' } if ($dlpPolicies.Count -eq 0) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'FAIL' ` -CurrentValue 'No Power Platform DLP policies configured — connectors are unrestricted and data can flow between any services' ` -Details @{ PolicyCount = 0 } } # Check for tenant-wide vs environment-specific policies $tenantPolicies = @($dlpPolicies | Where-Object { $_.EnvironmentType -eq 'AllEnvironments' -or $_.Scope -eq 'Tenant' -or $_.IsDefault -eq $true }) $envPolicies = @($dlpPolicies | Where-Object { $_.EnvironmentType -ne 'AllEnvironments' -and $_.Scope -ne 'Tenant' -and $_.IsDefault -ne $true }) $status = if ($tenantPolicies.Count -gt 0) { 'PASS' } elseif ($envPolicies.Count -gt 0) { 'WARN' } else { 'WARN' } return New-AuditFinding -CheckDefinition $CheckDefinition -Status $status ` -CurrentValue "$($dlpPolicies.Count) DLP policies ($($tenantPolicies.Count) tenant-wide, $($envPolicies.Count) environment-specific)" ` -Details @{ TotalPolicies = $dlpPolicies.Count TenantWidePolicies = $tenantPolicies.Count EnvironmentPolicies = $envPolicies.Count Policies = @($dlpPolicies | Select-Object -First 20 | ForEach-Object { @{ DisplayName = $_.DisplayName EnvironmentType = $_.EnvironmentType Scope = $_.Scope IsDefault = $_.IsDefault CreatedTime = $_.CreatedTime } }) } } # ── M365PP-003: Tenant Isolation ───────────────────────────────────── function Test-InfiltrationM365PP003 { [CmdletBinding()] param([hashtable]$AuditData, [hashtable]$CheckDefinition) $pp = $AuditData.M365Services.PowerPlatform if (-not $pp) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'SKIP' ` -CurrentValue 'Power Platform data not available (Power Platform admin module not connected)' } $tenantIsolationEnabled = $pp.TenantIsolationEnabled $tenantIsolationConfig = $pp.TenantIsolationConfig if ($null -eq $tenantIsolationEnabled -and $null -eq $tenantIsolationConfig) { return New-AuditFinding -CheckDefinition $CheckDefinition -Status 'SKIP' ` -CurrentValue 'Power Platform tenant isolation settings not available' } # Determine isolation state from available data $isolated = $false if ($null -ne $tenantIsolationEnabled) { $isolated = $tenantIsolationEnabled -eq $true } elseif ($null -ne $tenantIsolationConfig) { $isolated = $tenantIsolationConfig.Enabled -eq $true -or $tenantIsolationConfig.IsDisabled -eq $false } $status = if ($isolated) { 'PASS' } else { 'FAIL' } $description = if ($isolated) { 'Power Platform tenant isolation is enabled — cross-tenant connector traffic is blocked' } else { 'Power Platform tenant isolation is NOT enabled — connectors can communicate with external tenants' } $details = @{ TenantIsolationEnabled = $isolated } # Add allowed tenants if available if ($tenantIsolationConfig -and $tenantIsolationConfig.AllowedTenants) { $details['AllowedTenantCount'] = $tenantIsolationConfig.AllowedTenants.Count $details['AllowedTenants'] = @($tenantIsolationConfig.AllowedTenants | Select-Object -First 20 | ForEach-Object { @{ TenantId = $_.TenantId TenantName = $_.TenantName Direction = $_.Direction } }) } return New-AuditFinding -CheckDefinition $CheckDefinition -Status $status ` -CurrentValue $description ` -Details $details } |