diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index fa633af804..bb5b4b65d7 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - `compute_instance_suspended_without_persistent_disks` check for GCP provider [(#9747)](https://github.com/prowler-cloud/prowler/pull/9747) - `codebuild_project_webhook_filters_use_anchored_patterns` check for AWS provider to detect CodeBreach vulnerability [(#9840)](https://github.com/prowler-cloud/prowler/pull/9840) +- `defender_safelinks_policy_enabled` check for M365 provider [(#9832)](https://github.com/prowler-cloud/prowler/pull/9832) ### Changed diff --git a/prowler/lib/powershell/powershell.py b/prowler/lib/powershell/powershell.py index 8142fa8e45..9b809e667e 100644 --- a/prowler/lib/powershell/powershell.py +++ b/prowler/lib/powershell/powershell.py @@ -193,10 +193,30 @@ class PowerShellSession: result = default if error_result: - logger.error(f"PowerShell error output: {error_result}") + self._process_error(error_result) return result + def _process_error(self, error_result: str) -> None: + """ + Process PowerShell error output. + + This method handles error output from PowerShell commands. + Subclasses can override this to provide integration-specific error handling. + + Args: + error_result (str): The error output from PowerShell. + """ + if "is not recognized as a name of a cmdlet" in error_result: + cmdlet_match = re.search(r"'([^']+)'.*is not recognized", error_result) + cmdlet_name = cmdlet_match.group(1) if cmdlet_match else "Unknown" + logger.warning( + f"PowerShell cmdlet '{cmdlet_name}' is not available. " + f"This may indicate missing modules or insufficient permissions." + ) + else: + logger.error(f"PowerShell error output: {error_result}") + def json_parse_output(self, output: str) -> dict: """ Parse command execution output to JSON format. diff --git a/prowler/providers/m365/lib/powershell/m365_powershell.py b/prowler/providers/m365/lib/powershell/m365_powershell.py index 2324c77166..5744658881 100644 --- a/prowler/providers/m365/lib/powershell/m365_powershell.py +++ b/prowler/providers/m365/lib/powershell/m365_powershell.py @@ -1,4 +1,7 @@ import os +import re + +from typing_extensions import override from prowler.lib.logger import logger from prowler.lib.powershell.powershell import PowerShellSession @@ -46,6 +49,28 @@ class M365PowerShell(PowerShellSession): self.tenant_identity = identity self.init_credential(credentials) + @override + def _process_error(self, error_result: str) -> None: + """ + Process PowerShell error output with M365-specific context. + + Provides Microsoft 365 specific error messaging, particularly for + cmdlets that require Microsoft Defender for Office 365 licensing. + + Args: + error_result (str): The error output from PowerShell. + """ + if "is not recognized as a name of a cmdlet" in error_result: + cmdlet_match = re.search(r"'([^']+)'.*is not recognized", error_result) + cmdlet_name = cmdlet_match.group(1) if cmdlet_match else "Unknown" + logger.warning( + f"PowerShell cmdlet '{cmdlet_name}' is not available. " + f"This may indicate missing licensing (e.g., Microsoft Defender for Office 365) " + f"or insufficient permissions. Related checks will be skipped." + ) + else: + logger.error(f"PowerShell error output: {error_result}") + def clean_certificate_content(self, cert_content: str) -> str: """ Clean certificate content for PowerShell consumption.