diff --git a/README.md b/README.md index 2df9b00fb6..addd596590 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, Fe | GCP | 79 | 13 | 7 | 3 | | Azure | 140 | 18 | 8 | 3 | | Kubernetes | 83 | 7 | 4 | 7 | -| Microsoft365 | 5 | 2 | 1 | 0 | +| M365 | 5 | 2 | 1 | 0 | | NHN (Unofficial) | 6 | 2 | 1 | 0 | > You can list the checks, services, compliance frameworks and categories with `prowler --list-checks`, `prowler --list-services`, `prowler --list-compliance` and `prowler --list-categories`. diff --git a/docs/developer-guide/provider.md b/docs/developer-guide/provider.md index 6f6b1ca0ae..823f694a77 100644 --- a/docs/developer-guide/provider.md +++ b/docs/developer-guide/provider.md @@ -175,7 +175,7 @@ Due to the complexity and differences of each provider use the rest of the provi - [GCP](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/gcp/gcp_provider.py) - [Azure](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/azure/azure_provider.py) - [Kubernetes](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/kubernetes/kubernetes_provider.py) -- [Microsoft365](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/microsoft365/microsoft365_provider.py) +- [M365](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/m365/m365_provider.py) To facilitate understanding here is a pseudocode of how the most basic provider could be with examples. diff --git a/docs/developer-guide/services.md b/docs/developer-guide/services.md index d551a58269..6859bd0c07 100644 --- a/docs/developer-guide/services.md +++ b/docs/developer-guide/services.md @@ -237,4 +237,4 @@ It is really important to check if the current Prowler's permissions for each pr - AWS: https://docs.prowler.cloud/en/latest/getting-started/requirements/#aws-authentication - Azure: https://docs.prowler.cloud/en/latest/getting-started/requirements/#permissions - GCP: https://docs.prowler.cloud/en/latest/getting-started/requirements/#gcp-authentication -- Microsoft365: https://docs.prowler.cloud/en/latest/getting-started/requirements/#microsoft365-authentication +- M365: https://docs.prowler.cloud/en/latest/getting-started/requirements/#m365-authentication diff --git a/docs/getting-started/requirements.md b/docs/getting-started/requirements.md index 53d60c6a11..6e4ba9c267 100644 --- a/docs/getting-started/requirements.md +++ b/docs/getting-started/requirements.md @@ -40,8 +40,8 @@ If your IAM entity enforces MFA you can use `--mfa` and Prowler will ask you to Prowler for Azure supports the following authentication types. To use each one you need to pass the proper flag to the execution: -- [Service principal application](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser#service-principal-object) (recommended). -- Current az cli credentials stored. +- [Service Principal Application](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser#service-principal-object) (recommended). +- Current AZ CLI credentials stored. - Interactive browser authentication. - [Managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) authentication. @@ -119,12 +119,13 @@ The above settings must be associated to a user or service account. ???+ note By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned. -## Microsoft365 +## Microsoft 365 -Prowler for Microsoft365 currently supports the following authentication types: +Prowler for M365 currently supports the following authentication types: -- [Service principal application](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser#service-principal-object) (recommended). -- Current az cli credentials stored. +- [Service Principal Application](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser#service-principal-object). +- Service Principal Application and Microsoft User Credentials (**recommended**). +- Current AZ CLI credentials stored. - Interactive browser authentication. @@ -144,6 +145,35 @@ export AZURE_TENANT_ID="XXXXXXXXX" If you try to execute Prowler with the `--sp-env-auth` flag and those variables are empty or not exported, the execution is going to fail. Follow the instructions in the [Create Prowler Service Principal](../tutorials/azure/create-prowler-service-principal.md) section to create a service principal. +### Service Principal and User Credentials authentication (recommended) +This authentication method follows the same approach as the service principal method but introduces two additional environment variables for user credentials: `M365_USER` and `M365_ENCRYPTED_PASSWORD`. + +```console +export AZURE_CLIENT_ID="XXXXXXXXX" +export AZURE_CLIENT_SECRET="XXXXXXXXX" +export AZURE_TENANT_ID="XXXXXXXXX" +export M365_USER="your_email@example.com" +export M365_ENCRYPTED_PASSWORD="6500780061006d0070006c006500700061007300730077006f0072006400" # replace this to yours +``` + +These two new environment variables are required to execute the PowerShell modules needed to retrieve information from M365 services. Prowler will use service principal authentication to log into MS Graph and user credentials to authenticate to Microsoft PowerShell modules. + +The `M365_USER` should be your Microsoft account email, and `M365_ENCRYPTED_PASSWORD` must be an encrypted SecureString. +To convert your password into a valid encrypted string, run the following commands in PowerShell: + +```console +$securePassword = ConvertTo-SecureString "examplepassword" -AsPlainText -Force +$encryptedPassword = $securePassword | ConvertFrom-SecureString +``` + +If everything is done correctly, you will see the encrypted string that you need to set as the `M365_ENCRYPTED_PASSWORD` environment variable. +```console +Write-Output $encryptedPassword +6500780061006d0070006c006500700061007300730077006f0072006400 +``` + + + ### Interactive Browser authentication To use `--browser-auth` the user needs to authenticate against Azure using the default browser to start the scan, also `--tenant-id` flag is required. diff --git a/docs/index.md b/docs/index.md index 52c37e29cf..ac8d50461f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -170,7 +170,7 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler/), * `Python >= 3.9, <= 3.12` * `Python pip >= 21.0.0` - * AWS, GCP, Azure, Microsoft365 and/or Kubernetes credentials + * AWS, GCP, Azure, M365 and/or Kubernetes credentials _Commands_: @@ -423,7 +423,7 @@ While the scan is running, start exploring the findings in these sections: ### Prowler CLI -To run Prowler, you will need to specify the provider (e.g `aws`, `gcp`, `azure`, `microsoft365` or `kubernetes`): +To run Prowler, you will need to specify the provider (e.g `aws`, `gcp`, `azure`, `m365` or `kubernetes`): ???+ note If no provider specified, AWS will be used for backward compatibility with most of v2 options. @@ -565,23 +565,23 @@ kubectl logs prowler-XXXXX --namespace prowler-ns ???+ note By default, `prowler` will scan all namespaces in your active Kubernetes context. Use the flag `--context` to specify the context to be scanned and `--namespaces` to specify the namespaces to be scanned. -#### Microsoft365 +#### Microsoft 365 -With Microsoft365 you need to specify which auth method is going to be used: +With M365 you need to specify which auth method is going to be used: ```console # To use service principal authentication -prowler microsoft365 --sp-env-auth +prowler m365 --sp-env-auth # To use az cli authentication -prowler microsoft365 --az-cli-auth +prowler m365 --az-cli-auth # To use browser authentication -prowler microsoft365 --browser-auth --tenant-id "XXXXXXXX" +prowler m365 --browser-auth --tenant-id "XXXXXXXX" ``` -See more details about Microsoft365 Authentication in [Requirements](getting-started/requirements.md#microsoft365) +See more details about M365 Authentication in [Requirements](getting-started/requirements/#microsoft-365) ## Prowler v2 Documentation For **Prowler v2 Documentation**, please check it out [here](https://github.com/prowler-cloud/prowler/blob/8818f47333a0c1c1a457453c87af0ea5b89a385f/README.md). diff --git a/docs/tutorials/configuration_file.md b/docs/tutorials/configuration_file.md index 6a54e72bf2..9ee25ea7e7 100644 --- a/docs/tutorials/configuration_file.md +++ b/docs/tutorials/configuration_file.md @@ -97,14 +97,15 @@ The following list includes all the Kubernetes checks with configurable variable | `kubelet_strong_ciphers_only` | `kubelet_strong_ciphers` | String | -## Microsoft365 +## M365 ### Configurable Checks -The following list includes all the Microsoft365 checks with configurable variables that can be changed in the configuration yaml file: +The following list includes all the Microsoft 365 checks with configurable variables that can be changed in the configuration yaml file: | Check Name | Value | Type | |---------------------------------------------------------------|--------------------------------------------------|-----------------| | `entra_admin_users_sign_in_frequency_enabled` | `sign_in_frequency` | Integer | +| `teams_external_file_sharing_restricted` | `allowed_cloud_storage_services` | List of Strings | ## Config YAML File Structure @@ -504,10 +505,20 @@ kubernetes: "TLS_RSA_WITH_AES_128_GCM_SHA256", ] -# Microsoft365 Configuration -microsoft365: - # Conditional Access Policy - # policy.session_controls.sign_in_frequency.frequency in hours - sign_in_frequency: 4 +# M365 Configuration +m365: + # Entra Conditional Access Policy + # m365.entra_admin_users_sign_in_frequency_enabled + sign_in_frequency: 4 # 4 hours + # Teams Settings + # m365.teams_external_file_sharing_restricted + allowed_cloud_storage_services: + [ + #"allow_box", + #"allow_drop_box", + #"allow_egnyte", + #"allow_google_drive", + #"allow_share_file", + ] ``` diff --git a/docs/tutorials/microsoft365/authentication.md b/docs/tutorials/microsoft365/authentication.md index 750352ed76..f8bd9d13d4 100644 --- a/docs/tutorials/microsoft365/authentication.md +++ b/docs/tutorials/microsoft365/authentication.md @@ -1,23 +1,28 @@ -# Microsoft365 authentication +# Microsoft 365 authentication By default Prowler uses MsGraph Python SDK identity package authentication methods using the class `ClientSecretCredential`. -This allows Prowler to authenticate against microsoft365 using the following methods: +This allows Prowler to authenticate against Microsoft 365 using the following methods: - Service principal authentication by environment variables (Enterprise Application) +- Service principal and Microsoft user credentials by environment variabled (using PowerShell requires this authentication method) - Current CLI credentials stored - Interactive browser authentication + To launch the tool first you need to specify which method is used through the following flags: ```console +# To use service principal (app) authentication and Microsoft user credentials (to use PowerShell) +prowler m365 --env-auth + # To use service principal authentication -prowler microsoft365 --sp-env-auth +prowler m365 --sp-env-auth # To use cli authentication -prowler microsoft365 --az-cli-auth +prowler m365 --az-cli-auth # To use browser authentication -prowler microsoft365 --browser-auth --tenant-id "XXXXXXXX" +prowler m365 --browser-auth --tenant-id "XXXXXXXX" ``` -To use Prowler you need to set up also the permissions required to access your resources in your Microsoft365 account, to more details refer to [Requirements](../../getting-started/requirements.md) +To use Prowler you need to set up also the permissions required to access your resources in your Microsoft 365 account, to more details refer to [Requirements](../../getting-started/requirements.md#microsoft-365) diff --git a/examples/sdk/aws_scan.ipynb b/examples/sdk/aws_scan.ipynb index e6294a081a..f19b3ad897 100644 --- a/examples/sdk/aws_scan.ipynb +++ b/examples/sdk/aws_scan.ipynb @@ -66,7 +66,7 @@ "# from prowler.providers.gcp.gcp_provider import GcpProvider\n", "# from prowler.providers.azure.azure_provider import AzureProvider\n", "# from prowler.providers.kubernetes.kubernetes_provider import KubernetesProvider\n", - "# from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider" + "# from prowler.providers.m365.m365_provider import M365Provider" ] }, { diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index d77e549d8d..441ca9979a 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. - Add SOC2 compliance framework to Azure [(#7489)](https://github.com/prowler-cloud/prowler/pull/7489). - Add check for unused Service Accounts in GCP [(#7419)](https://github.com/prowler-cloud/prowler/pull/7419). +- Add Powershell to Microsoft365 [(#7331)](https://github.com/prowler-cloud/prowler/pull/7331) ### Fixed diff --git a/prowler/__main__.py b/prowler/__main__.py index f7e617ebcc..3bacaf291f 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -51,7 +51,7 @@ from prowler.lib.outputs.compliance.cis.cis_aws import AWSCIS from prowler.lib.outputs.compliance.cis.cis_azure import AzureCIS from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS -from prowler.lib.outputs.compliance.cis.cis_microsoft365 import Microsoft365CIS +from prowler.lib.outputs.compliance.cis.cis_m365 import M365CIS from prowler.lib.outputs.compliance.compliance import display_compliance_table from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS @@ -85,7 +85,7 @@ from prowler.providers.common.provider import Provider from prowler.providers.common.quick_inventory import run_provider_quick_inventory from prowler.providers.gcp.models import GCPOutputOptions from prowler.providers.kubernetes.models import KubernetesOutputOptions -from prowler.providers.microsoft365.models import Microsoft365OutputOptions +from prowler.providers.m365.models import M365OutputOptions from prowler.providers.nhn.models import NHNOutputOptions @@ -268,8 +268,8 @@ def prowler(): output_options = KubernetesOutputOptions( args, bulk_checks_metadata, global_provider.identity ) - elif provider == "microsoft365": - output_options = Microsoft365OutputOptions( + elif provider == "m365": + output_options = M365OutputOptions( args, bulk_checks_metadata, global_provider.identity ) elif provider == "nhn": @@ -666,7 +666,7 @@ def prowler(): generated_outputs["compliance"].append(generic_compliance) generic_compliance.batch_write_data_to_file() - elif provider == "microsoft365": + elif provider == "m365": for compliance_name in input_compliance_frameworks: if compliance_name.startswith("cis_"): # Generate CIS Finding Object @@ -674,7 +674,7 @@ def prowler(): f"{output_options.output_directory}/compliance/" f"{output_options.output_filename}_{compliance_name}.csv" ) - cis = Microsoft365CIS( + cis = M365CIS( findings=finding_outputs, compliance=bulk_compliance_frameworks[compliance_name], file_path=filename, diff --git a/prowler/compliance/microsoft365/__init__.py b/prowler/compliance/m365/__init__.py similarity index 100% rename from prowler/compliance/microsoft365/__init__.py rename to prowler/compliance/m365/__init__.py diff --git a/prowler/compliance/microsoft365/cis_4.0_microsoft365.json b/prowler/compliance/m365/cis_4.0_m365.json similarity index 99% rename from prowler/compliance/microsoft365/cis_4.0_microsoft365.json rename to prowler/compliance/m365/cis_4.0_m365.json index ca26b4a467..a85f8a953d 100644 --- a/prowler/compliance/microsoft365/cis_4.0_microsoft365.json +++ b/prowler/compliance/m365/cis_4.0_m365.json @@ -1,7 +1,7 @@ { "Framework": "CIS", "Version": "4.0", - "Provider": "Microsoft365", + "Provider": "M365", "Description": "The CIS Microsoft 365 Foundations Benchmark provides prescriptive guidance for establishing a secure configuration posture for Microsoft 365 Cloud offerings running on any OS.", "Requirements": [ { diff --git a/prowler/config/config.py b/prowler/config/config.py index 2239ce4c32..38d0134859 100644 --- a/prowler/config/config.py +++ b/prowler/config/config.py @@ -28,7 +28,7 @@ class Provider(str, Enum): GCP = "gcp" AZURE = "azure" KUBERNETES = "kubernetes" - MICROSOFT365 = "microsoft365" + M365 = "m365" NHN = "nhn" @@ -126,7 +126,7 @@ def load_and_validate_config_file(provider: str, config_file_path: str) -> dict: # and a new format with a key for each provider to include their configuration values within. if any( key in config_file - for key in ["aws", "gcp", "azure", "kubernetes", "microsoft365"] + for key in ["aws", "gcp", "azure", "kubernetes", "m365"] ): config = config_file.get(provider, {}) else: diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index c9b1e773bc..c8a2ee7e50 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -483,8 +483,18 @@ kubernetes: ] -# Microsoft365 Configuration -microsoft365: - # Conditional Access Policy - # policy.session_controls.sign_in_frequency.frequency in hours - sign_in_frequency: 4 +# M365 Configuration +m365: + # Entra Conditional Access Policy + # m365.entra_admin_users_sign_in_frequency_enabled + sign_in_frequency: 4 # 4 hours + # Teams Settings + # m365.teams_external_file_sharing_restricted + allowed_cloud_storage_services: + [ + #"allow_box", + #"allow_drop_box", + #"allow_egnyte", + #"allow_google_drive", + #"allow_share_file", + ] diff --git a/prowler/config/microsoft365_mutelist_example.yaml b/prowler/config/m365_mutelist_example.yaml similarity index 96% rename from prowler/config/microsoft365_mutelist_example.yaml rename to prowler/config/m365_mutelist_example.yaml index c33b442c04..34fda956e0 100644 --- a/prowler/config/microsoft365_mutelist_example.yaml +++ b/prowler/config/m365_mutelist_example.yaml @@ -1,5 +1,5 @@ ### Account, Check and/or Region can be * to apply for all the cases. -### Account == Microsoft365 Tenant and Region == Microsoft365 Location +### Account == M365 Tenant and Region == M365 Location ### Resources and tags are lists that can have either Regex or Keywords. ### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together. ### Use an alternation Regex to match one of multiple tags with "ORed" logic. diff --git a/prowler/lib/check/models.py b/prowler/lib/check/models.py index b76424f495..88e4d83aa7 100644 --- a/prowler/lib/check/models.py +++ b/prowler/lib/check/models.py @@ -543,8 +543,8 @@ class Check_Report_Kubernetes(Check_Report): @dataclass -class CheckReportMicrosoft365(Check_Report): - """Contains the Microsoft365 Check's finding information.""" +class CheckReportM365(Check_Report): + """Contains the M365 Check's finding information.""" resource_name: str resource_id: str @@ -558,7 +558,7 @@ class CheckReportMicrosoft365(Check_Report): resource_id: str, resource_location: str = "global", ) -> None: - """Initialize the Microsoft365 Check's finding information. + """Initialize the M365 Check's finding information. Args: metadata: The metadata of the check. diff --git a/prowler/lib/cli/parser.py b/prowler/lib/cli/parser.py index 0a5f63074d..f2cc8d12dd 100644 --- a/prowler/lib/cli/parser.py +++ b/prowler/lib/cli/parser.py @@ -26,15 +26,15 @@ class ProwlerArgumentParser: self.parser = argparse.ArgumentParser( prog="prowler", formatter_class=RawTextHelpFormatter, - usage="prowler [-h] [--version] {aws,azure,gcp,kubernetes,microsoft365,nhn,dashboard} ...", + usage="prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,nhn,dashboard} ...", epilog=""" Available Cloud Providers: - {aws,azure,gcp,kubernetes,microsoft365,nhn} + {aws,azure,gcp,kubernetes,m365,nhn} aws AWS Provider azure Azure Provider gcp GCP Provider kubernetes Kubernetes Provider - microsoft365 Microsoft 365 Provider + m365 Microsoft 365 Provider nhn NHN Provider (Unofficial) Available components: @@ -104,6 +104,11 @@ Detailed documentation at https://docs.prowler.com if "-" in sys.argv[1]: sys.argv = self.__set_default_provider__(sys.argv) + # Provider aliases mapping + # Microsoft 365 + elif sys.argv[1] == "microsoft365": + sys.argv[1] = "m365" + # Parse arguments args = self.parser.parse_args() diff --git a/prowler/lib/outputs/compliance/cis/cis_microsoft365.py b/prowler/lib/outputs/compliance/cis/cis_m365.py similarity index 95% rename from prowler/lib/outputs/compliance/cis/cis_microsoft365.py rename to prowler/lib/outputs/compliance/cis/cis_m365.py index 8cf4722ba7..a587d98214 100644 --- a/prowler/lib/outputs/compliance/cis/cis_microsoft365.py +++ b/prowler/lib/outputs/compliance/cis/cis_m365.py @@ -1,10 +1,10 @@ from prowler.lib.check.compliance_models import Compliance -from prowler.lib.outputs.compliance.cis.models import Microsoft365CISModel +from prowler.lib.outputs.compliance.cis.models import M365CISModel from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput from prowler.lib.outputs.finding import Finding -class Microsoft365CIS(ComplianceOutput): +class M365CIS(ComplianceOutput): """ This class represents the Azure CIS compliance output. @@ -39,7 +39,7 @@ class Microsoft365CIS(ComplianceOutput): for requirement in compliance.Requirements: if requirement.Id in finding_requirements: for attribute in requirement.Attributes: - compliance_row = Microsoft365CISModel( + compliance_row = M365CISModel( Provider=finding.provider, Description=compliance.Description, TenantId=finding.account_uid, @@ -70,7 +70,7 @@ class Microsoft365CIS(ComplianceOutput): for requirement in compliance.Requirements: if not requirement.Checks: for attribute in requirement.Attributes: - compliance_row = Microsoft365CISModel( + compliance_row = M365CISModel( Provider=compliance.Provider.lower(), Description=compliance.Description, TenantId=finding.account_uid, diff --git a/prowler/lib/outputs/compliance/cis/models.py b/prowler/lib/outputs/compliance/cis/models.py index 1f6e661655..201925f19d 100644 --- a/prowler/lib/outputs/compliance/cis/models.py +++ b/prowler/lib/outputs/compliance/cis/models.py @@ -69,9 +69,9 @@ class AzureCISModel(BaseModel): Muted: bool -class Microsoft365CISModel(BaseModel): +class M365CISModel(BaseModel): """ - Microsoft365CISModel generates a finding's output in Microsoft365 CIS Compliance format. + M365CISModel generates a finding's output in Microsoft 365 CIS Compliance format. """ Provider: str diff --git a/prowler/lib/outputs/finding.py b/prowler/lib/outputs/finding.py index b1c8299887..f8aab16555 100644 --- a/prowler/lib/outputs/finding.py +++ b/prowler/lib/outputs/finding.py @@ -245,7 +245,7 @@ class Finding(BaseModel): ) output_data["region"] = f"namespace: {check_output.namespace}" - elif provider.type == "microsoft365": + elif provider.type == "m365": output_data["auth_method"] = ( f"{provider.identity.identity_type}: {provider.identity.identity_id}" ) diff --git a/prowler/lib/outputs/html/html.py b/prowler/lib/outputs/html/html.py index 8e3c88efd6..d9177a4ab9 100644 --- a/prowler/lib/outputs/html/html.py +++ b/prowler/lib/outputs/html/html.py @@ -546,9 +546,9 @@ class HTML(Output): return "" @staticmethod - def get_microsoft365_assessment_summary(provider: Provider) -> str: + def get_m365_assessment_summary(provider: Provider) -> str: """ - get_microsoft365_assessment_summary gets the HTML assessment summary for the provider + get_m365_assessment_summary gets the HTML assessment summary for the provider Args: provider (Provider): the provider object @@ -561,11 +561,11 @@ class HTML(Output):
- Microsoft365 Assessment Summary + M365 Assessment Summary
  • - Microsoft365 Tenant Domain: {provider.identity.tenant_domain} + M365 Tenant Domain: {provider.identity.tenant_domain}
@@ -573,14 +573,14 @@ class HTML(Output):
- Microsoft365 Credentials + M365 Credentials
  • - Microsoft365 Identity Type: {provider.identity.identity_type} + M365 Identity Type: {provider.identity.identity_type}
  • - Microsoft365 Identity ID: {provider.identity.identity_id} + M365 Identity ID: {provider.identity.identity_id}
diff --git a/prowler/lib/outputs/outputs.py b/prowler/lib/outputs/outputs.py index 0912f986af..bb635510ac 100644 --- a/prowler/lib/outputs/outputs.py +++ b/prowler/lib/outputs/outputs.py @@ -16,7 +16,7 @@ def stdout_report(finding, color, verbose, status, fix): details = finding.location.lower() if finding.check_metadata.Provider == "kubernetes": details = finding.namespace.lower() - if finding.check_metadata.Provider == "microsoft365": + if finding.check_metadata.Provider == "m365": details = finding.location if finding.check_metadata.Provider == "nhn": details = finding.location diff --git a/prowler/lib/outputs/summary_table.py b/prowler/lib/outputs/summary_table.py index b860285e2e..8d8dbc0e95 100644 --- a/prowler/lib/outputs/summary_table.py +++ b/prowler/lib/outputs/summary_table.py @@ -40,7 +40,7 @@ def display_summary_table( elif provider.type == "kubernetes": entity_type = "Context" audited_entities = provider.identity.context - elif provider.type == "microsoft365": + elif provider.type == "m365": entity_type = "Tenant Domain" audited_entities = provider.identity.tenant_domain elif provider.type == "nhn": diff --git a/prowler/providers/microsoft365/__init__.py b/prowler/lib/powershell/__init__.py similarity index 100% rename from prowler/providers/microsoft365/__init__.py rename to prowler/lib/powershell/__init__.py diff --git a/prowler/lib/powershell/powershell.py b/prowler/lib/powershell/powershell.py new file mode 100644 index 0000000000..373fc97183 --- /dev/null +++ b/prowler/lib/powershell/powershell.py @@ -0,0 +1,222 @@ +import json +import platform +import queue +import re +import subprocess +import threading + + +class PowerShellSession: + """ + Base class for managing PowerShell sessions. + + This class provides the core functionality for interacting with PowerShell, + including command execution, output handling, and session management. + It serves as a foundation for more specific PowerShell implementations. + + Features: + - Maintains a persistent PowerShell session + - Handles command execution and output parsing + - Provides secure input sanitization + - Manages ANSI escape sequence removal + - Supports JSON output parsing + - Implements timeout handling for long-running commands + + Attributes: + END (str): Marker string used to signal the end of PowerShell command output. + process (subprocess.Popen): The underlying PowerShell subprocess with open stdin, stdout, and stderr streams. + + Note: + This is an abstract base class that should be extended by specific implementations + for different PowerShell use cases. + """ + + END = "" + + def __init__(self): + """ + Initialize a persistent PowerShell session. + + Creates a subprocess running PowerShell with pipes for stdin, stdout, and stderr. + The session is configured to run in interactive mode with no exit. + + Note: + This is a base implementation that should be extended by subclasses + to add specific initialization logic (e.g., credential setup). + """ + # Determine the appropriate PowerShell command based on the OS + if platform.system() == "Windows": + powershell_cmd = "powershell" + else: + powershell_cmd = "pwsh" + + self.process = subprocess.Popen( + [powershell_cmd, "-NoExit", "-Command", "-"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + bufsize=1, + ) + + def sanitize(self, credential: str) -> str: + """ + Sanitize input to prevent command injection. + + Filters the input string to allow only letters, numbers, @, periods, underscores, + plus signs, and hyphens. This is a security measure to prevent command injection + attacks through credential input. + + Args: + credential (str): The string to sanitize. + + Returns: + str: The sanitized string containing only allowed characters. + + Example: + >>> sanitize("user@domain.com!@#$") + "user@domain.com" + """ + return re.sub(r"[^a-zA-Z0-9@._+\-]", "", credential) + + def remove_ansi(self, text: str) -> str: + """ + Remove ANSI color codes and other escape sequences from PowerShell output. + + PowerShell often includes ANSI escape sequences in its output for terminal + coloring and formatting. This method strips these sequences to produce clean, + parseable text that can be processed programmatically. + + Args: + text (str): Raw text containing ANSI escape sequences from PowerShell output. + + Returns: + str: Clean text with all ANSI escape sequences removed, suitable for parsing. + + Example: + >>> remove_ansi("\x1b[32mSuccess\x1b[0m") + "Success" + """ + ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + return ansi_escape.sub("", text) + + def execute(self, command: str) -> dict: + """ + Send a command to PowerShell and retrieve its output. + + Executes the given command in the PowerShell session, adds an END marker, + and parses the output as JSON if possible. The command is executed + asynchronously with a timeout mechanism. + + Args: + command (str): PowerShell command to execute. + + Returns: + dict: JSON-parsed output if available, otherwise an empty dictionary. + + Example: + >>> execute("Get-Process | ConvertTo-Json") + {"Name": "process1", "Id": 1234} + """ + self.process.stdin.write(f"{command}\n") + self.process.stdin.write(f"Write-Output '{self.END}'\n") + return self.json_parse_output(self.read_output()) + + def read_output(self, timeout: int = 10, default: str = "") -> str: + """ + Read output from a process with timeout functionality. + + This method reads lines from process stdout until it encounters the END marker + or the stream ends. If reading takes longer than the timeout period, the method + returns a default value while allowing the reading to continue in the background. + + Args: + timeout (int, optional): Maximum time in seconds to wait for output. + Defaults to 10. + default (str, optional): Value to return if timeout occurs. + Defaults to empty string. + + Returns: + str: Concatenated output lines or default value if timeout occurs. + + Note: + This method uses a daemon thread to read the output asynchronously, + ensuring that the main thread is not blocked. + """ + output_lines = [] + result_queue = queue.Queue() + + def reader_thread(): + try: + while True: + line = self.remove_ansi(self.process.stdout.readline().strip()) + if line == self.END: + break + output_lines.append(line) + result_queue.put("\n".join(output_lines)) + except Exception as e: + result_queue.put(str(e)) + + thread = threading.Thread(target=reader_thread) + thread.daemon = True + thread.start() + + try: + return result_queue.get(timeout=timeout) + except queue.Empty: + return default + + def json_parse_output(self, output: str) -> dict: + """ + Parse command execution output to JSON format. + + Searches for a JSON object in the output string and parses it. + The method looks for both object and array JSON structures. + + Args: + output (str): The string output from a PowerShell command. + + Returns: + dict: Parsed JSON object if found, otherwise an empty dictionary. + + Example: + >>> json_parse_output('Some text {"key": "value"} more text') + {"key": "value"} + """ + json_match = re.search(r"(\[.*\]|\{.*\})", output, re.DOTALL) + if json_match: + return json.loads(json_match.group(1)) + return {} + + def close(self) -> None: + """ + Terminate the PowerShell session. + + Sends an exit command to PowerShell and terminates the subprocess. + This method should be called when the session is no longer needed + to ensure proper cleanup of resources. + + Note: + It's important to call this method when done with the session + to prevent resource leaks. + """ + if self.process: + try: + # Send exit command + self.process.stdin.write("exit\n") + self.process.stdin.flush() + + # Terminate the process + self.process.terminate() + + # Wait for the process to finish + self.process.wait(timeout=5) + except Exception: + # If process is still running, force kill it + self.process.kill() + finally: + # Close all pipes + self.process.stdin.close() + self.process.stdout.close() + self.process.stderr.close() + self.process = None diff --git a/prowler/providers/common/provider.py b/prowler/providers/common/provider.py index b8fe46d9e8..0efde909ef 100644 --- a/prowler/providers/common/provider.py +++ b/prowler/providers/common/provider.py @@ -211,12 +211,13 @@ class Provider(ABC): mutelist_path=arguments.mutelist_file, fixer_config=fixer_config, ) - elif "microsoft365" in provider_class_name.lower(): + elif "m365" in provider_class_name.lower(): provider_class( region=arguments.region, config_path=arguments.config_file, mutelist_path=arguments.mutelist_file, sp_env_auth=arguments.sp_env_auth, + env_auth=arguments.env_auth, az_cli_auth=arguments.az_cli_auth, browser_auth=arguments.browser_auth, tenant_id=arguments.tenant_id, diff --git a/prowler/providers/microsoft365/lib/__init__.py b/prowler/providers/m365/__init__.py similarity index 100% rename from prowler/providers/microsoft365/lib/__init__.py rename to prowler/providers/m365/__init__.py diff --git a/prowler/providers/microsoft365/exceptions/exceptions.py b/prowler/providers/m365/exceptions/exceptions.py similarity index 58% rename from prowler/providers/microsoft365/exceptions/exceptions.py rename to prowler/providers/m365/exceptions/exceptions.py index 45c645802d..9f9c96a178 100644 --- a/prowler/providers/microsoft365/exceptions/exceptions.py +++ b/prowler/providers/m365/exceptions/exceptions.py @@ -1,103 +1,111 @@ from prowler.exceptions.exceptions import ProwlerException -# Exceptions codes from 5000 to 5999 are reserved for Microsoft365 exceptions -class Microsoft365BaseException(ProwlerException): - """Base class for Microsoft365 Errors.""" +# Exceptions codes from 5000 to 5999 are reserved for M365 exceptions +class M365BaseException(ProwlerException): + """Base class for M365 Errors.""" MICROSOFT365_ERROR_CODES = { - (6000, "Microsoft365EnvironmentVariableError"): { - "message": "Microsoft365 environment variable error", - "remediation": "Check the Microsoft365 environment variables and ensure they are properly set.", + (6000, "M365EnvironmentVariableError"): { + "message": "Microsoft 365 environment variable error", + "remediation": "Check the Microsoft 365 environment variables and ensure they are properly set.", }, - (6001, "Microsoft365ArgumentTypeValidationError"): { - "message": "Microsoft365 argument type validation error", - "remediation": "Check the provided argument types specific to Microsoft365 and ensure they meet the required format.", + (6001, "M365ArgumentTypeValidationError"): { + "message": "Microsoft 365 argument type validation error", + "remediation": "Check the provided argument types specific to Microsoft 365 and ensure they meet the required format.", }, - (6002, "Microsoft365SetUpRegionConfigError"): { - "message": "Microsoft365 region configuration setup error", - "remediation": "Check the Microsoft365 region configuration and ensure it is properly set up.", + (6002, "M365SetUpRegionConfigError"): { + "message": "Microsoft 365 region configuration setup error", + "remediation": "Check the Microsoft 365 region configuration and ensure it is properly set up.", }, - (6003, "Microsoft365HTTPResponseError"): { - "message": "Error in HTTP response from Microsoft365", + (6003, "M365HTTPResponseError"): { + "message": "Error in HTTP response from Microsoft 365", "remediation": "", }, - (6004, "Microsoft365CredentialsUnavailableError"): { - "message": "Error trying to configure Microsoft365 credentials because they are unavailable", - "remediation": "Check the dictionary and ensure it is properly set up for Microsoft365 credentials. TENANT_ID, CLIENT_ID and CLIENT_SECRET are required.", + (6004, "M365CredentialsUnavailableError"): { + "message": "Error trying to configure Microsoft 365 credentials because they are unavailable", + "remediation": "Check the dictionary and ensure it is properly set up for Microsoft 365 credentials. TENANT_ID, CLIENT_ID and CLIENT_SECRET are required.", }, - (6005, "Microsoft365GetTokenIdentityError"): { - "message": "Error trying to get token from Microsoft365 Identity", - "remediation": "Check the Microsoft365 Identity and ensure it is properly set up.", + (6005, "M365GetTokenIdentityError"): { + "message": "Error trying to get token from Microsoft 365 Identity", + "remediation": "Check the Microsoft 365 Identity and ensure it is properly set up.", }, - (6006, "Microsoft365ClientAuthenticationError"): { + (6006, "M365ClientAuthenticationError"): { "message": "Error in client authentication", "remediation": "Check the client authentication and ensure it is properly set up.", }, - (6007, "Microsoft365NotValidTenantIdError"): { + (6007, "M365NotValidTenantIdError"): { "message": "The provided tenant ID is not valid", "remediation": "Check the tenant ID and ensure it is a valid ID.", }, - (6008, "Microsoft365NotValidClientIdError"): { + (6008, "M365NotValidClientIdError"): { "message": "The provided client ID is not valid", "remediation": "Check the client ID and ensure it is a valid ID.", }, - (6009, "Microsoft365NotValidClientSecretError"): { + (6009, "M365NotValidClientSecretError"): { "message": "The provided client secret is not valid", "remediation": "Check the client secret and ensure it is a valid secret.", }, - (6010, "Microsoft365ConfigCredentialsError"): { - "message": "Error in configuration of Microsoft365 credentials", - "remediation": "Check the configuration of Microsoft365 credentials and ensure it is properly set up.", + (6010, "M365ConfigCredentialsError"): { + "message": "Error in configuration of Microsoft 365 credentials", + "remediation": "Check the configuration of Microsoft 365 credentials and ensure it is properly set up.", }, - (6011, "Microsoft365ClientIdAndClientSecretNotBelongingToTenantIdError"): { + (6011, "M365ClientIdAndClientSecretNotBelongingToTenantIdError"): { "message": "The provided client ID and client secret do not belong to the provided tenant ID", "remediation": "Check the client ID and client secret and ensure they belong to the provided tenant ID.", }, - (6012, "Microsoft365TenantIdAndClientSecretNotBelongingToClientIdError"): { + (6012, "M365TenantIdAndClientSecretNotBelongingToClientIdError"): { "message": "The provided tenant ID and client secret do not belong to the provided client ID", "remediation": "Check the tenant ID and client secret and ensure they belong to the provided client ID.", }, - (6013, "Microsoft365TenantIdAndClientIdNotBelongingToClientSecretError"): { + (6013, "M365TenantIdAndClientIdNotBelongingToClientSecretError"): { "message": "The provided tenant ID and client ID do not belong to the provided client secret", "remediation": "Check the tenant ID and client ID and ensure they belong to the provided client secret.", }, - (6014, "Microsoft365InvalidProviderIdError"): { + (6014, "M365InvalidProviderIdError"): { "message": "The provided provider_id does not match with the available subscriptions", "remediation": "Check the provider_id and ensure it is a valid subscription for the given credentials.", }, - (6015, "Microsoft365NoAuthenticationMethodError"): { - "message": "No Microsoft365 authentication method found", - "remediation": "Check that any authentication method is properly set up for Microsoft365.", + (6015, "M365NoAuthenticationMethodError"): { + "message": "No Microsoft 365 authentication method found", + "remediation": "Check that any authentication method is properly set up for Microsoft 365.", }, - (6016, "Microsoft365SetUpSessionError"): { + (6016, "M365SetUpSessionError"): { "message": "Error setting up session", "remediation": "Check the session setup and ensure it is properly set up.", }, - (6017, "Microsoft365DefaultAzureCredentialError"): { + (6017, "M365DefaultAzureCredentialError"): { "message": "Error with DefaultAzureCredential", "remediation": "Ensure DefaultAzureCredential is correctly configured.", }, - (6018, "Microsoft365InteractiveBrowserCredentialError"): { + (6018, "M365InteractiveBrowserCredentialError"): { "message": "Error with InteractiveBrowserCredential", "remediation": "Ensure InteractiveBrowserCredential is correctly configured.", }, - (6019, "Microsoft365BrowserAuthNoTenantIDError"): { - "message": "Microsoft365 Tenant ID (--tenant-id) is required for browser authentication mode", - "remediation": "Check the Microsoft365 Tenant ID and ensure it is properly set up.", + (6019, "M365BrowserAuthNoTenantIDError"): { + "message": "Microsoft 365 Tenant ID (--tenant-id) is required for browser authentication mode", + "remediation": "Check the Microsoft 365 Tenant ID and ensure it is properly set up.", }, - (6020, "Microsoft365BrowserAuthNoFlagError"): { - "message": "Microsoft365 tenant ID error: browser authentication flag (--browser-auth) not found", + (6020, "M365BrowserAuthNoFlagError"): { + "message": "Microsoft 365 tenant ID error: browser authentication flag (--browser-auth) not found", "remediation": "To use browser authentication, ensure the tenant ID is properly set.", }, - (6021, "Microsoft365NotTenantIdButClientIdAndClientSecretError"): { - "message": "Tenant Id is required for Microsoft365 static credentials. Make sure you are using the correct credentials.", - "remediation": "Check the Microsoft365 Tenant ID and ensure it is properly set up.", + (6021, "M365NotTenantIdButClientIdAndClientSecretError"): { + "message": "Tenant Id is required for Microsoft 365 static credentials. Make sure you are using the correct credentials.", + "remediation": "Check the Microsoft 365 Tenant ID and ensure it is properly set up.", + }, + (6022, "M365MissingEnvironmentUserCredentialsError"): { + "message": "User and Password environment variables are needed to use Credentials authentication method.", + "remediation": "Ensure your environment variables are properly set up.", + }, + (6023, "M365EnvironmentUserCredentialsError"): { + "message": "User or Password environment variables are not correct.", + "remediation": "Ensure you are using the right credentials.", }, } def __init__(self, code, file=None, original_exception=None, message=None): - provider = "Microsoft365" + provider = "M365" error_info = self.MICROSOFT365_ERROR_CODES.get((code, self.__class__.__name__)) if message: error_info["message"] = message @@ -110,170 +118,176 @@ class Microsoft365BaseException(ProwlerException): ) -class Microsoft365CredentialsError(Microsoft365BaseException): - """Base class for Microsoft365 credentials errors.""" +class M365CredentialsError(M365BaseException): + """Base class for M365 credentials errors.""" def __init__(self, code, file=None, original_exception=None, message=None): super().__init__(code, file, original_exception, message) -class Microsoft365EnvironmentVariableError(Microsoft365CredentialsError): +class M365EnvironmentVariableError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6000, file=file, original_exception=original_exception, message=message ) -class Microsoft365ArgumentTypeValidationError(Microsoft365BaseException): +class M365ArgumentTypeValidationError(M365BaseException): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6001, file=file, original_exception=original_exception, message=message ) -class Microsoft365SetUpRegionConfigError(Microsoft365BaseException): +class M365SetUpRegionConfigError(M365BaseException): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6002, file=file, original_exception=original_exception, message=message ) -class Microsoft365HTTPResponseError(Microsoft365BaseException): +class M365HTTPResponseError(M365BaseException): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6003, file=file, original_exception=original_exception, message=message ) -class Microsoft365CredentialsUnavailableError(Microsoft365CredentialsError): +class M365CredentialsUnavailableError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6004, file=file, original_exception=original_exception, message=message ) -class Microsoft365GetTokenIdentityError(Microsoft365BaseException): +class M365GetTokenIdentityError(M365BaseException): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6005, file=file, original_exception=original_exception, message=message ) -class Microsoft365ClientAuthenticationError(Microsoft365CredentialsError): +class M365ClientAuthenticationError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6006, file=file, original_exception=original_exception, message=message ) -class Microsoft365NotValidTenantIdError(Microsoft365CredentialsError): +class M365NotValidTenantIdError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6007, file=file, original_exception=original_exception, message=message ) -class Microsoft365NotValidClientIdError(Microsoft365CredentialsError): +class M365NotValidClientIdError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6008, file=file, original_exception=original_exception, message=message ) -class Microsoft365NotValidClientSecretError(Microsoft365CredentialsError): +class M365NotValidClientSecretError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6009, file=file, original_exception=original_exception, message=message ) -class Microsoft365ConfigCredentialsError(Microsoft365CredentialsError): +class M365ConfigCredentialsError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6010, file=file, original_exception=original_exception, message=message ) -class Microsoft365ClientIdAndClientSecretNotBelongingToTenantIdError( - Microsoft365CredentialsError -): +class M365ClientIdAndClientSecretNotBelongingToTenantIdError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6011, file=file, original_exception=original_exception, message=message ) -class Microsoft365TenantIdAndClientSecretNotBelongingToClientIdError( - Microsoft365CredentialsError -): +class M365TenantIdAndClientSecretNotBelongingToClientIdError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6012, file=file, original_exception=original_exception, message=message ) -class Microsoft365TenantIdAndClientIdNotBelongingToClientSecretError( - Microsoft365CredentialsError -): +class M365TenantIdAndClientIdNotBelongingToClientSecretError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6013, file=file, original_exception=original_exception, message=message ) -class Microsoft365InvalidProviderIdError(Microsoft365BaseException): +class M365InvalidProviderIdError(M365BaseException): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6014, file=file, original_exception=original_exception, message=message ) -class Microsoft365NoAuthenticationMethodError(Microsoft365CredentialsError): +class M365NoAuthenticationMethodError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6015, file=file, original_exception=original_exception, message=message ) -class Microsoft365SetUpSessionError(Microsoft365CredentialsError): +class M365SetUpSessionError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6016, file=file, original_exception=original_exception, message=message ) -class Microsoft365DefaultAzureCredentialError(Microsoft365CredentialsError): +class M365DefaultAzureCredentialError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6017, file=file, original_exception=original_exception, message=message ) -class Microsoft365InteractiveBrowserCredentialError(Microsoft365CredentialsError): +class M365InteractiveBrowserCredentialError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6018, file=file, original_exception=original_exception, message=message ) -class Microsoft365BrowserAuthNoTenantIDError(Microsoft365CredentialsError): +class M365BrowserAuthNoTenantIDError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6019, file=file, original_exception=original_exception, message=message ) -class Microsoft365BrowserAuthNoFlagError(Microsoft365CredentialsError): +class M365BrowserAuthNoFlagError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6020, file=file, original_exception=original_exception, message=message ) -class Microsoft365NotTenantIdButClientIdAndClientSecretError( - Microsoft365CredentialsError -): +class M365NotTenantIdButClientIdAndClientSecretError(M365CredentialsError): def __init__(self, file=None, original_exception=None, message=None): super().__init__( 6021, file=file, original_exception=original_exception, message=message ) + + +class M365MissingEnvironmentUserCredentialsError(M365CredentialsError): + def __init__(self, file=None, original_exception=None, message=None): + super().__init__( + 6022, file=file, original_exception=original_exception, message=message + ) + + +class M365EnvironmentUserCredentialsError(M365CredentialsError): + def __init__(self, file=None, original_exception=None, message=None): + super().__init__( + 6023, file=file, original_exception=original_exception, message=message + ) diff --git a/prowler/providers/microsoft365/lib/arguments/__init__.py b/prowler/providers/m365/lib/__init__.py similarity index 100% rename from prowler/providers/microsoft365/lib/arguments/__init__.py rename to prowler/providers/m365/lib/__init__.py diff --git a/prowler/providers/microsoft365/lib/mutelist/__init__.py b/prowler/providers/m365/lib/arguments/__init__.py similarity index 100% rename from prowler/providers/microsoft365/lib/mutelist/__init__.py rename to prowler/providers/m365/lib/arguments/__init__.py diff --git a/prowler/providers/m365/lib/arguments/arguments.py b/prowler/providers/m365/lib/arguments/arguments.py new file mode 100644 index 0000000000..a1980c4bd9 --- /dev/null +++ b/prowler/providers/m365/lib/arguments/arguments.py @@ -0,0 +1,61 @@ +def init_parser(self): + """Init the M365 Provider CLI parser""" + m365_parser = self.subparsers.add_parser( + "m365", + parents=[self.common_providers_parser], + help="M365 Provider", + ) + # Authentication Modes + m365_auth_subparser = m365_parser.add_argument_group("Authentication Modes") + m365_auth_modes_group = m365_auth_subparser.add_mutually_exclusive_group() + m365_auth_modes_group.add_argument( + "--az-cli-auth", + action="store_true", + help="Use Azure CLI authentication to log in against Microsoft 365", + ) + m365_auth_modes_group.add_argument( + "--env-auth", + action="store_true", + help="Use User and Password environment variables authentication to log in against Microsoft 365", + ) + m365_auth_modes_group.add_argument( + "--sp-env-auth", + action="store_true", + help="Use Azure Service Principal environment variables authentication to log in against Microsoft 365", + ) + m365_auth_modes_group.add_argument( + "--browser-auth", + action="store_true", + help="Use Azure interactive browser authentication to log in against Microsoft 365", + ) + m365_parser.add_argument( + "--tenant-id", + nargs="?", + default=None, + help="Microsoft 365 Tenant ID to be used with --browser-auth option", + ) + m365_parser.add_argument( + "--user", + nargs="?", + default=None, + help="Microsoft 365 user email", + ) + m365_parser.add_argument( + "--encypted-password", + nargs="?", + default=None, + help="Microsoft 365 encrypted password", + ) + # Regions + m365_regions_subparser = m365_parser.add_argument_group("Regions") + m365_regions_subparser.add_argument( + "--region", + nargs="?", + default="M365Global", + choices=[ + "M365Global", + "M365GlobalChina", + "M365USGovernment", + ], + help="Microsoft 365 region to be used, default is M365Global", + ) diff --git a/prowler/providers/microsoft365/lib/regions/__init__.py b/prowler/providers/m365/lib/mutelist/__init__.py similarity index 100% rename from prowler/providers/microsoft365/lib/regions/__init__.py rename to prowler/providers/m365/lib/mutelist/__init__.py diff --git a/prowler/providers/microsoft365/lib/mutelist/mutelist.py b/prowler/providers/m365/lib/mutelist/mutelist.py similarity index 74% rename from prowler/providers/microsoft365/lib/mutelist/mutelist.py rename to prowler/providers/m365/lib/mutelist/mutelist.py index 21669d9d04..a7bf971f3e 100644 --- a/prowler/providers/microsoft365/lib/mutelist/mutelist.py +++ b/prowler/providers/m365/lib/mutelist/mutelist.py @@ -1,12 +1,12 @@ -from prowler.lib.check.models import CheckReportMicrosoft365 +from prowler.lib.check.models import CheckReportM365 from prowler.lib.mutelist.mutelist import Mutelist from prowler.lib.outputs.utils import unroll_dict, unroll_tags -class Microsoft365Mutelist(Mutelist): +class M365Mutelist(Mutelist): def is_finding_muted( self, - finding: CheckReportMicrosoft365, + finding: CheckReportM365, ) -> bool: return self.is_muted( finding.tenant_id, diff --git a/prowler/providers/m365/lib/powershell/m365_powershell.py b/prowler/providers/m365/lib/powershell/m365_powershell.py new file mode 100644 index 0000000000..367b1fe2af --- /dev/null +++ b/prowler/providers/m365/lib/powershell/m365_powershell.py @@ -0,0 +1,171 @@ +import msal + +from prowler.lib.powershell.powershell import PowerShellSession +from prowler.providers.m365.models import M365Credentials + + +class M365PowerShell(PowerShellSession): + """ + Microsoft 365 specific PowerShell session management implementation. + + This class extends the base PowerShellSession to provide Microsoft 365 specific + functionality, including authentication, Teams management, and Exchange Online + operations. + + Features: + - Microsoft 365 credential management + - Teams client configuration + - Exchange Online connectivity + - Audit log configuration + - Secure credential handling + + Attributes: + credentials (M365Credentials): The Microsoft 365 credentials used for authentication. + + Note: + This class requires the Microsoft Teams and Exchange Online PowerShell modules + to be installed and available in the PowerShell environment. + """ + + def __init__(self, credentials: M365Credentials): + """ + Initialize a Microsoft 365 PowerShell session. + + Sets up the PowerShell session and initializes the provided credentials + for Microsoft 365 authentication. + + Args: + credentials (M365Credentials): The Microsoft 365 credentials to use + for authentication. + """ + super().__init__() + self.init_credential(credentials) + + def init_credential(self, credentials: M365Credentials) -> None: + """ + Initialize PowerShell credential object for Microsoft 365 authentication. + + Sanitizes the username and password, then creates a PSCredential object + in the PowerShell session for use with Microsoft 365 cmdlets. + + Args: + credentials (M365Credentials): The credentials object containing + username and password. + + Note: + The credentials are sanitized to prevent command injection and + stored securely in the PowerShell session. + """ + # Sanitize user and password + user = self.sanitize(credentials.user) + passwd = self.sanitize(credentials.passwd) + + # Securely convert encrypted password to SecureString + self.execute(f'$user = "{user}"') + self.execute(f'$secureString = "{passwd}" | ConvertTo-SecureString') + self.execute( + "$credential = New-Object System.Management.Automation.PSCredential ($user, $secureString)" + ) + + def test_credentials(self, credentials: M365Credentials) -> bool: + """ + Test Microsoft 365 credentials by attempting to authenticate against Entra ID. + + Args: + credentials (M365Credentials): The credentials object containing + username and password to test. + + Returns: + bool: True if credentials are valid and authentication succeeds, False otherwise. + """ + self.execute( + f'$securePassword = "{credentials.passwd}" | ConvertTo-SecureString\n' + ) + self.execute( + f'$credential = New-Object System.Management.Automation.PSCredential("{credentials.user}", $securePassword)\n' + ) + self.process.stdin.write( + 'Write-Output "$($credential.GetNetworkCredential().Password)"\n' + ) + self.process.stdin.write(f"Write-Output '{self.END}'\n") + decrypted_password = self.read_output() + + app = msal.ConfidentialClientApplication( + client_id=credentials.client_id, + client_credential=credentials.client_secret, + authority=f"https://login.microsoftonline.com/{credentials.tenant_id}", + ) + + result = app.acquire_token_by_username_password( + username=credentials.user, + password=decrypted_password, # Needs to be in plain text + scopes=["https://graph.microsoft.com/.default"], + ) + + return "access_token" in result + + def connect_microsoft_teams(self) -> dict: + """ + Connect to Microsoft Teams Module PowerShell Module. + + Establishes a connection to Microsoft Teams using the initialized credentials. + + Returns: + dict: Connection status information in JSON format. + + Note: + This method requires the Microsoft Teams PowerShell module to be installed. + """ + return self.execute("Connect-MicrosoftTeams -Credential $credential") + + def get_teams_settings(self) -> dict: + """ + Get Teams Client Settings. + + Retrieves the current Microsoft Teams client configuration settings. + + Returns: + dict: Teams client configuration settings in JSON format. + + Example: + >>> get_teams_settings() + { + "AllowBox": true, + "AllowDropBox": true, + "AllowGoogleDrive": true + } + """ + return self.execute("Get-CsTeamsClientConfiguration | ConvertTo-Json") + + def connect_exchange_online(self) -> dict: + """ + Connect to Exchange Online PowerShell Module. + + Establishes a connection to Exchange Online using the initialized credentials. + + Returns: + dict: Connection status information in JSON format. + + Note: + This method requires the Exchange Online PowerShell module to be installed. + """ + return self.execute("Connect-ExchangeOnline -Credential $credential") + + def get_audit_log_config(self) -> dict: + """ + Get Purview Admin Audit Log Settings. + + Retrieves the current audit log configuration settings for Microsoft Purview. + + Returns: + dict: Audit log configuration settings in JSON format. + + Example: + >>> get_audit_log_config() + { + "UnifiedAuditLogIngestionEnabled": true + } + """ + return self.execute( + "Get-AdminAuditLogConfig | Select-Object UnifiedAuditLogIngestionEnabled | ConvertTo-Json" + ) diff --git a/prowler/providers/microsoft365/lib/service/__init__.py b/prowler/providers/m365/lib/regions/__init__.py similarity index 100% rename from prowler/providers/microsoft365/lib/service/__init__.py rename to prowler/providers/m365/lib/regions/__init__.py diff --git a/prowler/providers/microsoft365/lib/regions/regions.py b/prowler/providers/m365/lib/regions/regions.py similarity index 90% rename from prowler/providers/microsoft365/lib/regions/regions.py rename to prowler/providers/m365/lib/regions/regions.py index b9e6d1969a..1f3fd8cfbf 100644 --- a/prowler/providers/microsoft365/lib/regions/regions.py +++ b/prowler/providers/m365/lib/regions/regions.py @@ -8,17 +8,17 @@ MICROSOFT365_GENERIC_CLOUD = "https://graph.microsoft.com" def get_regions_config(region): allowed_regions = { - "Microsoft365Global": { + "M365Global": { "authority": None, "base_url": MICROSOFT365_GENERIC_CLOUD, "credential_scopes": [MICROSOFT365_GENERIC_CLOUD + "/.default"], }, - "Microsoft365China": { + "M365China": { "authority": AzureAuthorityHosts.AZURE_CHINA, "base_url": MICROSOFT365_CHINA_CLOUD, "credential_scopes": [MICROSOFT365_CHINA_CLOUD + "/.default"], }, - "Microsoft365USGovernment": { + "M365USGovernment": { "authority": AzureAuthorityHosts.AZURE_GOVERNMENT, "base_url": MICROSOFT365_US_GOV_CLOUD, "credential_scopes": [MICROSOFT365_US_GOV_CLOUD + "/.default"], diff --git a/prowler/providers/microsoft365/services/admincenter/__init__.py b/prowler/providers/m365/lib/service/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/admincenter/__init__.py rename to prowler/providers/m365/lib/service/__init__.py diff --git a/prowler/providers/m365/lib/service/service.py b/prowler/providers/m365/lib/service/service.py new file mode 100644 index 0000000000..02aeb2762c --- /dev/null +++ b/prowler/providers/m365/lib/service/service.py @@ -0,0 +1,17 @@ +from msgraph import GraphServiceClient + +from prowler.providers.m365.lib.powershell.m365_powershell import M365PowerShell +from prowler.providers.m365.m365_provider import M365Provider + + +class M365Service: + def __init__( + self, + provider: M365Provider, + ): + self.client = GraphServiceClient(credentials=provider.session) + self.audit_config = provider.audit_config + self.fixer_config = provider.fixer_config + + if provider.credentials: + self.powershell = M365PowerShell(provider.credentials) diff --git a/prowler/providers/microsoft365/microsoft365_provider.py b/prowler/providers/m365/m365_provider.py similarity index 57% rename from prowler/providers/microsoft365/microsoft365_provider.py rename to prowler/providers/m365/m365_provider.py index 668381d576..cd4438da72 100644 --- a/prowler/providers/microsoft365/microsoft365_provider.py +++ b/prowler/providers/m365/m365_provider.py @@ -25,88 +25,96 @@ from prowler.lib.logger import logger from prowler.lib.utils.utils import print_boxes from prowler.providers.common.models import Audit_Metadata, Connection from prowler.providers.common.provider import Provider -from prowler.providers.microsoft365.exceptions.exceptions import ( - Microsoft365ArgumentTypeValidationError, - Microsoft365BrowserAuthNoFlagError, - Microsoft365BrowserAuthNoTenantIDError, - Microsoft365ClientAuthenticationError, - Microsoft365ClientIdAndClientSecretNotBelongingToTenantIdError, - Microsoft365ConfigCredentialsError, - Microsoft365CredentialsUnavailableError, - Microsoft365DefaultAzureCredentialError, - Microsoft365EnvironmentVariableError, - Microsoft365GetTokenIdentityError, - Microsoft365HTTPResponseError, - Microsoft365InteractiveBrowserCredentialError, - Microsoft365InvalidProviderIdError, - Microsoft365NoAuthenticationMethodError, - Microsoft365NotTenantIdButClientIdAndClientSecretError, - Microsoft365NotValidClientIdError, - Microsoft365NotValidClientSecretError, - Microsoft365NotValidTenantIdError, - Microsoft365SetUpRegionConfigError, - Microsoft365SetUpSessionError, - Microsoft365TenantIdAndClientIdNotBelongingToClientSecretError, - Microsoft365TenantIdAndClientSecretNotBelongingToClientIdError, +from prowler.providers.m365.exceptions.exceptions import ( + M365ArgumentTypeValidationError, + M365BrowserAuthNoFlagError, + M365BrowserAuthNoTenantIDError, + M365ClientAuthenticationError, + M365ClientIdAndClientSecretNotBelongingToTenantIdError, + M365ConfigCredentialsError, + M365CredentialsUnavailableError, + M365DefaultAzureCredentialError, + M365EnvironmentUserCredentialsError, + M365EnvironmentVariableError, + M365GetTokenIdentityError, + M365HTTPResponseError, + M365InteractiveBrowserCredentialError, + M365InvalidProviderIdError, + M365MissingEnvironmentUserCredentialsError, + M365NoAuthenticationMethodError, + M365NotTenantIdButClientIdAndClientSecretError, + M365NotValidClientIdError, + M365NotValidClientSecretError, + M365NotValidTenantIdError, + M365SetUpRegionConfigError, + M365SetUpSessionError, + M365TenantIdAndClientIdNotBelongingToClientSecretError, + M365TenantIdAndClientSecretNotBelongingToClientIdError, ) -from prowler.providers.microsoft365.lib.mutelist.mutelist import Microsoft365Mutelist -from prowler.providers.microsoft365.lib.regions.regions import get_regions_config -from prowler.providers.microsoft365.models import ( - Microsoft365IdentityInfo, - Microsoft365RegionConfig, +from prowler.providers.m365.lib.mutelist.mutelist import M365Mutelist +from prowler.providers.m365.lib.powershell.m365_powershell import M365PowerShell +from prowler.providers.m365.lib.regions.regions import get_regions_config +from prowler.providers.m365.models import ( + M365Credentials, + M365IdentityInfo, + M365RegionConfig, ) -class Microsoft365Provider(Provider): +class M365Provider(Provider): """ - Represents an Microsoft365 provider. + Represents an M365 provider. - This class provides functionality to interact with the Microsoft365 resources. + This class provides functionality to interact with the M365 resources. It handles authentication, region configuration, and provides access to various properties and methods - related to the Microsoft365 provider. + related to the M365 provider. Attributes: - _type (str): The type of the provider, which is set to "microsoft365". - _session (DefaultMicrosoft365Credential): The session object associated with the Microsoft365 provider. - _identity (Microsoft365IdentityInfo): The identity information for the Microsoft365 provider. - _audit_config (dict): The audit configuration for the Microsoft365 provider. - _region_config (Microsoft365RegionConfig): The region configuration for the Microsoft365 provider. - _mutelist (Microsoft365Mutelist): The mutelist object associated with the Microsoft365 provider. - audit_metadata (Audit_Metadata): The audit metadata for the Microsoft365 provider. + _type (str): The type of the provider, which is set to "m365". + _session (DefaultM365Credential): The session object associated with the M365 provider. + _identity (M365IdentityInfo): The identity information for the M365 provider. + _audit_config (dict): The audit configuration for the M365 provider. + _region_config (M365RegionConfig): The region configuration for the M365 provider. + _mutelist (M365Mutelist): The mutelist object associated with the M365 provider. + audit_metadata (Audit_Metadata): The audit metadata for the M365 provider. Methods: - __init__ -> Initializes the Microsoft365 provider. - identity(self): Returns the identity of the Microsoft365 provider. - type(self): Returns the type of the Microsoft365 provider. - session(self): Returns the session object associated with the Microsoft365 provider. - region_config(self): Returns the region configuration for the Microsoft365 provider. - audit_config(self): Returns the audit configuration for the Microsoft365 provider. + __init__ -> Initializes the M365 provider. + identity(self): Returns the identity of the M365 provider. + type(self): Returns the type of the M365 provider. + session(self): Returns the session object associated with the M365 provider. + region_config(self): Returns the region configuration for the M365 provider. + audit_config(self): Returns the audit configuration for the M365 provider. fixer_config(self): Returns the fixer configuration. - output_options(self, options: tuple): Sets the output options for the Microsoft365 provider. - mutelist(self) -> Microsoft365Mutelist: Returns the mutelist object associated with the Microsoft365 provider. - setup_region_config(cls, region): Sets up the region configuration for the Microsoft365 provider. - print_credentials(self): Prints the Microsoft365 credentials information. - setup_session(cls, az_cli_auth, app_env_auth, browser_auth, managed_identity_auth, tenant_id, region_config): Set up the Microsoft365 session with the specified authentication method. + output_options(self, options: tuple): Sets the output options for the M365 provider. + mutelist(self) -> M365Mutelist: Returns the mutelist object associated with the M365 provider. + setup_region_config(cls, region): Sets up the region configuration for the M365 provider. + print_credentials(self): Prints the M365 credentials information. + setup_session(cls, az_cli_auth, app_env_auth, browser_auth, managed_identity_auth, tenant_id, region_config): Set up the M365 session with the specified authentication method. """ - _type: str = "microsoft365" + _type: str = "m365" _session: DefaultAzureCredential # Must be used besides being named for Azure - _identity: Microsoft365IdentityInfo + _identity: M365IdentityInfo _audit_config: dict - _region_config: Microsoft365RegionConfig - _mutelist: Microsoft365Mutelist + _region_config: M365RegionConfig + _mutelist: M365Mutelist + _credentials: M365Credentials # TODO: this is not optional, enforce for all providers audit_metadata: Audit_Metadata def __init__( self, sp_env_auth: bool, + env_auth: bool, az_cli_auth: bool, browser_auth: bool, tenant_id: str = None, client_id: str = None, client_secret: str = None, - region: str = "Microsoft365Global", + user: str = None, + encrypted_password: str = None, + region: str = "M365Global", config_content: dict = None, config_path: str = None, mutelist_path: str = None, @@ -114,13 +122,13 @@ class Microsoft365Provider(Provider): fixer_config: dict = {}, ): """ - Initializes the Microsoft365 provider. + Initializes the M365 provider. Args: - tenant_id (str): The Microsoft365 Active Directory tenant ID. - region (str): The Microsoft365 region. - client_id (str): The Microsoft365 client ID. - client_secret (str): The Microsoft365 client secret. + tenant_id (str): The M365 Active Directory tenant ID. + region (str): The M365 region. + client_id (str): The M365 client ID. + client_secret (str): The M365 client secret. config_path (str): The path to the configuration file. config_content (dict): The configuration content. fixer_config (dict): The fixer configuration. @@ -131,13 +139,13 @@ class Microsoft365Provider(Provider): None Raises: - Microsoft365ArgumentTypeValidationError: If there is an error in the argument type validation. - Microsoft365SetUpRegionConfigError: If there is an error in setting up the region configuration. - Microsoft365ConfigCredentialsError: If there is an error in configuring the Microsoft365 credentials from a dictionary. - Microsoft365GetTokenIdentityError: If there is an error in getting the token from the Microsoft365 identity. - Microsoft365HTTPResponseError: If there is an HTTP response error. + M365ArgumentTypeValidationError: If there is an error in the argument type validation. + M365SetUpRegionConfigError: If there is an error in setting up the region configuration. + M365ConfigCredentialsError: If there is an error in configuring the M365 credentials from a dictionary. + M365GetTokenIdentityError: If there is an error in getting the token from the M365 identity. + M365HTTPResponseError: If there is an HTTP response error. """ - logger.info("Setting Microsoft365 provider ...") + logger.info("Setting M365 provider ...") logger.info("Checking if any credentials mode is set ...") @@ -145,36 +153,48 @@ class Microsoft365Provider(Provider): self.validate_arguments( az_cli_auth, sp_env_auth, + env_auth, browser_auth, tenant_id, client_id, client_secret, + user, + encrypted_password, ) logger.info("Checking if region is different than default one") self._region_config = self.setup_region_config(region) # Get the dict from the static credentials - microsoft365_credentials = None - if tenant_id and client_id and client_secret: - microsoft365_credentials = self.validate_static_credentials( - tenant_id=tenant_id, client_id=client_id, client_secret=client_secret + m365_credentials = None + if tenant_id and client_id and client_secret and user and encrypted_password: + m365_credentials = self.validate_static_credentials( + tenant_id=tenant_id, + client_id=client_id, + client_secret=client_secret, + user=user, + encrypted_password=encrypted_password, ) - # Set up the Microsoft365 session + # Set up the M365 session self._session = self.setup_session( az_cli_auth, sp_env_auth, + env_auth, browser_auth, tenant_id, - microsoft365_credentials, + m365_credentials, self._region_config, ) + # Set up PowerShell session credentials + self._credentials = self.setup_powershell(env_auth, m365_credentials) + # Set up the identity self._identity = self.setup_identity( az_cli_auth, sp_env_auth, + env_auth, browser_auth, client_id, ) @@ -192,13 +212,13 @@ class Microsoft365Provider(Provider): # Mutelist if mutelist_content: - self._mutelist = Microsoft365Mutelist( + self._mutelist = M365Mutelist( mutelist_content=mutelist_content, ) else: if not mutelist_path: mutelist_path = get_default_mute_file_path(self.type) - self._mutelist = Microsoft365Mutelist( + self._mutelist = M365Mutelist( mutelist_path=mutelist_path, ) @@ -206,27 +226,27 @@ class Microsoft365Provider(Provider): @property def identity(self): - """Returns the identity of the Microsoft365 provider.""" + """Returns the identity of the M365 provider.""" return self._identity @property def type(self): - """Returns the type of the Microsoft365 provider.""" + """Returns the type of the M365 provider.""" return self._type @property def session(self): - """Returns the session object associated with the Microsoft365 provider.""" + """Returns the session object associated with the M365 provider.""" return self._session @property def region_config(self): - """Returns the region configuration for the Microsoft365 provider.""" + """Returns the region configuration for the M365 provider.""" return self._region_config @property def audit_config(self): - """Returns the audit configuration for the Microsoft365 provider.""" + """Returns the audit configuration for the M365 provider.""" return self._audit_config @property @@ -235,73 +255,89 @@ class Microsoft365Provider(Provider): return self._fixer_config @property - def mutelist(self) -> Microsoft365Mutelist: - """Mutelist object associated with this Microsoft365 provider.""" + def mutelist(self) -> M365Mutelist: + """Mutelist object associated with this M365 provider.""" return self._mutelist + @property + def credentials(self) -> M365Credentials: + """Return powershell credentials""" + return self._credentials + @staticmethod def validate_arguments( az_cli_auth: bool, sp_env_auth: bool, + env_auth: bool, browser_auth: bool, tenant_id: str, client_id: str, client_secret: str, + user: str, + encrypted_password: str, ): """ - Validates the authentication arguments for the Microsoft365 provider. + Validates the authentication arguments for the M365 provider. Args: az_cli_auth (bool): Flag indicating whether Azure CLI authentication is enabled. sp_env_auth (bool): Flag indicating whether application authentication with environment variables is enabled. + env_auth: (bool): Flag indicating whether to use application and PowerShell authentication with environment variables. browser_auth (bool): Flag indicating whether browser authentication is enabled. - tenant_id (str): The Microsoft365 Tenant ID. - client_id (str): The Microsoft365 Client ID. - client_secret (str): The Microsoft365 Client Secret. + tenant_id (str): The M365 Tenant ID. + client_id (str): The M365 Client ID. + client_secret (str): The M365 Client Secret. + user (str): The M365 User Account. + encrpted_password (str): The M365 Encrypted Password. Raises: - Microsoft365BrowserAuthNoTenantIDError: If browser authentication is enabled but the tenant ID is not found. + M365BrowserAuthNoTenantIDError: If browser authentication is enabled but the tenant ID is not found. """ - if not client_id and not client_secret: + if not client_id and not client_secret and not user and not encrypted_password: if not browser_auth and tenant_id: - raise Microsoft365BrowserAuthNoFlagError( + raise M365BrowserAuthNoFlagError( file=os.path.basename(__file__), - message="Microsoft365 tenant ID error: browser authentication flag (--browser-auth) not found", + message="M365 tenant ID error: browser authentication flag (--browser-auth) not found", ) - elif not az_cli_auth and not sp_env_auth and not browser_auth: - raise Microsoft365NoAuthenticationMethodError( + elif ( + not az_cli_auth + and not sp_env_auth + and not browser_auth + and not env_auth + ): + raise M365NoAuthenticationMethodError( file=os.path.basename(__file__), - message="Microsoft365 provider requires at least one authentication method set: [--az-cli-auth | --sp-env-auth | --browser-auth]", + message="M365 provider requires at least one authentication method set: [--env-auth | --az-cli-auth | --sp-env-auth | --browser-auth]", ) elif browser_auth and not tenant_id: - raise Microsoft365BrowserAuthNoTenantIDError( + raise M365BrowserAuthNoTenantIDError( file=os.path.basename(__file__), - message="Microsoft365 Tenant ID (--tenant-id) is required for browser authentication mode", + message="M365 Tenant ID (--tenant-id) is required for browser authentication mode", ) else: if not tenant_id: - raise Microsoft365NotTenantIdButClientIdAndClientSecretError( + raise M365NotTenantIdButClientIdAndClientSecretError( file=os.path.basename(__file__), - message="Tenant Id is required for Microsoft365 static credentials. Make sure you are using the correct credentials.", + message="Tenant Id is required for M365 static credentials. Make sure you are using the correct credentials.", ) @staticmethod def setup_region_config(region): """ - Sets up the region configuration for the Microsoft365 provider. + Sets up the region configuration for the M365 provider. Args: region (str): The name of the region. Returns: - Microsoft365RegionConfig: The region configuration object. + M365RegionConfig: The region configuration object. """ try: config = get_regions_config(region) - return Microsoft365RegionConfig( + return M365RegionConfig( name=region, authority=config["authority"], base_url=config["base_url"], @@ -311,7 +347,7 @@ class Microsoft365Provider(Provider): logger.error( f"{validation_error.__class__.__name__}[{validation_error.__traceback__.tb_lineno}]: {validation_error}" ) - raise Microsoft365ArgumentTypeValidationError( + raise M365ArgumentTypeValidationError( file=os.path.basename(__file__), original_exception=validation_error, ) @@ -319,16 +355,74 @@ class Microsoft365Provider(Provider): logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - raise Microsoft365SetUpRegionConfigError( + raise M365SetUpRegionConfigError( file=os.path.basename(__file__), original_exception=error, ) - def print_credentials(self): - """Microsoft365 credentials information. + @staticmethod + def setup_powershell( + env_auth: bool = False, m365_credentials: dict = {} + ) -> M365Credentials: + """Gets the M365 credentials. - This method prints the Microsoft365 Tenant Domain, Microsoft365 Tenant ID, Microsoft365 Region, - Microsoft365 Subscriptions, Microsoft365 Identity Type, and Microsoft365 Identity ID. + Args: + env_auth: (bool): Flag indicating whether to use application and PowerShell authentication with environment variables. + + Returns: + M365Credentials: Object containing the user credentials. + If env_auth is True, retrieves from environment variables. + If False, returns empty credentials. + """ + credentials = None + if m365_credentials: + credentials = M365Credentials( + user=m365_credentials.get("user", ""), + passwd=m365_credentials.get("encrypted_password", ""), + client_id=m365_credentials.get("client_id", ""), + client_secret=m365_credentials.get("client_secret", ""), + tenant_id=m365_credentials.get("tenant_id", ""), + ) + elif env_auth: + m365_user = getenv("M365_USER") + m365_password = getenv("M365_ENCRYPTED_PASSWORD") + client_id = getenv("AZURE_CLIENT_ID") + client_secret = getenv("AZURE_CLIENT_SECRET") + tenant_id = getenv("AZURE_TENANT_ID") + + if not m365_user or not m365_password: + logger.critical( + "M365 provider: Missing M365_USER or M365_ENCRYPTED_PASSWORD environment variables needed for credentials authentication" + ) + raise M365MissingEnvironmentUserCredentialsError( + file=os.path.basename(__file__), + message="Missing M365_USER or M365_ENCRYPTED_PASSWORD environment variables required for credentials authentication.", + ) + credentials = M365Credentials( + user=m365_user, + passwd=m365_password, + client_id=client_id, + client_secret=client_secret, + tenant_id=tenant_id, + ) + + if credentials: + test_session = M365PowerShell(credentials) + try: + if test_session.test_credentials(credentials): + return credentials + raise M365EnvironmentUserCredentialsError( + file=os.path.basename(__file__), + message="M365_USER or M365_ENCRYPTED_PASSWORD environment variables are not correct. Please ensure you are using the right credentials.", + ) + finally: + test_session.close() + + def print_credentials(self): + """M365 credentials information. + + This method prints the M365 Tenant Domain, M365 Tenant ID, M365 Region, + M365 Subscriptions, M365 Identity Type, and M365 Identity ID. Args: None @@ -337,12 +431,13 @@ class Microsoft365Provider(Provider): None """ report_lines = [ - f"Microsoft365 Region: {Fore.YELLOW}{self.region_config.name}{Style.RESET_ALL}", - f"Microsoft365 Tenant Domain: {Fore.YELLOW}{self._identity.tenant_domain}{Style.RESET_ALL} Microsoft365 Tenant ID: {Fore.YELLOW}{self._identity.tenant_id}{Style.RESET_ALL}", - f"Microsoft365 Identity Type: {Fore.YELLOW}{self._identity.identity_type}{Style.RESET_ALL} Microsoft365 Identity ID: {Fore.YELLOW}{self._identity.identity_id}{Style.RESET_ALL}", + f"M365 Region: {Fore.YELLOW}{self.region_config.name}{Style.RESET_ALL}", + f"M365 Tenant Domain: {Fore.YELLOW}{self._identity.tenant_domain}{Style.RESET_ALL} M365 Tenant ID: {Fore.YELLOW}{self._identity.tenant_id}{Style.RESET_ALL}", + f"M365 Identity Type: {Fore.YELLOW}{self._identity.identity_type}{Style.RESET_ALL} M365 Identity ID: {Fore.YELLOW}{self._identity.identity_id}{Style.RESET_ALL}", + f"M365 User: {Fore.YELLOW}{self.credentials.user}{Style.RESET_ALL}", ] report_title = ( - f"{Style.BRIGHT}Using the Microsoft365 credentials below:{Style.RESET_ALL}" + f"{Style.BRIGHT}Using the M365 credentials below:{Style.RESET_ALL}" ) print_boxes(report_lines, report_title) @@ -352,72 +447,71 @@ class Microsoft365Provider(Provider): def setup_session( az_cli_auth: bool, sp_env_auth: bool, + env_auth: bool, browser_auth: bool, tenant_id: str, - microsoft365_credentials: dict, - region_config: Microsoft365RegionConfig, + m365_credentials: dict, + region_config: M365RegionConfig, ): - """Returns the Microsoft365 credentials object. + """Returns the M365 credentials object. - Set up the Microsoft365 session with the specified authentication method. + Set up the M365 session with the specified authentication method. Args: az_cli_auth (bool): Flag indicating whether to use Azure CLI authentication. sp_env_auth (bool): Flag indicating whether to use application authentication with environment variables. browser_auth (bool): Flag indicating whether to use interactive browser authentication. - tenant_id (str): The Microsoft365 Active Directory tenant ID. - microsoft365_credentials (dict): The Microsoft365 configuration object. It contains the following keys: - - tenant_id: The Microsoft365 Active Directory tenant ID. - - client_id: The Microsoft365 client ID. - - client_secret: The Microsoft365 client secret - region_config (Microsoft365RegionConfig): The region configuration object. + tenant_id (str): The M365 Active Directory tenant ID. + m365_credentials (dict): The M365 configuration object. It contains the following keys: + - tenant_id: The M365 Active Directory tenant ID. + - client_id: The M365 client ID. + - client_secret: The M365 client secret + region_config (M365RegionConfig): The region configuration object. Returns: - credentials: The Microsoft365 credentials object. + credentials: The M365 credentials object. Raises: - Exception: If failed to retrieve Microsoft365 credentials. + Exception: If failed to retrieve M365 credentials. """ if not browser_auth: - if sp_env_auth: + if sp_env_auth or env_auth: try: - Microsoft365Provider.check_service_principal_creds_env_vars() - except ( - Microsoft365EnvironmentVariableError - ) as environment_credentials_error: + M365Provider.check_service_principal_creds_env_vars() + except M365EnvironmentVariableError as environment_credentials_error: logger.critical( f"{environment_credentials_error.__class__.__name__}[{environment_credentials_error.__traceback__.tb_lineno}] -- {environment_credentials_error}" ) raise environment_credentials_error try: - if microsoft365_credentials: + if m365_credentials: try: credentials = ClientSecretCredential( - tenant_id=microsoft365_credentials["tenant_id"], - client_id=microsoft365_credentials["client_id"], - client_secret=microsoft365_credentials["client_secret"], + tenant_id=m365_credentials["tenant_id"], + client_id=m365_credentials["client_id"], + client_secret=m365_credentials["client_secret"], ) return credentials except ClientAuthenticationError as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365ClientAuthenticationError( + raise M365ClientAuthenticationError( file=os.path.basename(__file__), original_exception=error ) except CredentialUnavailableError as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365CredentialsUnavailableError( + raise M365CredentialsUnavailableError( file=os.path.basename(__file__), original_exception=error ) except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365ConfigCredentialsError( + raise M365ConfigCredentialsError( file=os.path.basename(__file__), original_exception=error ) else: @@ -425,15 +519,17 @@ class Microsoft365Provider(Provider): # DefaultAzureCredential sets just one authentication method, excluding the others try: credentials = DefaultAzureCredential( - exclude_environment_credential=not sp_env_auth, + exclude_environment_credential=not ( + sp_env_auth or env_auth + ), exclude_cli_credential=not az_cli_auth, - # Microsoft365 Auth using Managed Identity is not supported + # M365 Auth using Managed Identity is not supported exclude_managed_identity_credential=True, - # Microsoft365 Auth using Visual Studio is not supported + # M365 Auth using Visual Studio is not supported exclude_visual_studio_code_credential=True, - # Microsoft365 Auth using Shared Token Cache is not supported + # M365 Auth using Shared Token Cache is not supported exclude_shared_token_cache_credential=True, - # Microsoft365 Auth using PowerShell is not supported + # M365 Auth using PowerShell is not supported exclude_powershell_credential=True, # set Authority of a Microsoft Entra endpoint authority=region_config.authority, @@ -442,29 +538,29 @@ class Microsoft365Provider(Provider): logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365ClientAuthenticationError( + raise M365ClientAuthenticationError( file=os.path.basename(__file__), original_exception=error ) except CredentialUnavailableError as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365CredentialsUnavailableError( + raise M365CredentialsUnavailableError( file=os.path.basename(__file__), original_exception=error ) except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365DefaultAzureCredentialError( + raise M365DefaultAzureCredentialError( file=os.path.basename(__file__), original_exception=error ) except Exception as error: - logger.critical("Failed to retrieve Microsoft365 credentials") + logger.critical("Failed to retrieve M365 credentials") logger.critical( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365SetUpSessionError( + raise M365SetUpSessionError( file=os.path.basename(__file__), original_exception=error ) else: @@ -472,12 +568,12 @@ class Microsoft365Provider(Provider): credentials = InteractiveBrowserCredential(tenant_id=tenant_id) except Exception as error: logger.critical( - "Failed to retrieve Microsoft365 credentials using browser authentication" + "Failed to retrieve M365 credentials using browser authentication" ) logger.critical( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365InteractiveBrowserCredentialError( + raise M365InteractiveBrowserCredentialError( file=os.path.basename(__file__), original_exception=error ) @@ -487,95 +583,104 @@ class Microsoft365Provider(Provider): def test_connection( az_cli_auth: bool = False, sp_env_auth: bool = False, + env_auth: bool = False, browser_auth: bool = False, tenant_id: str = None, - region: str = "Microsoft365Global", + region: str = "M365Global", raise_on_exception=True, client_id=None, client_secret=None, + user=None, + encrypted_password=None, ) -> Connection: - """Test connection to Microsoft365 subscription. + """Test connection to M365 subscription. - Test the connection to an Microsoft365 subscription using the provided credentials. + Test the connection to an M365 subscription using the provided credentials. Args: az_cli_auth (bool): Flag indicating whether to use Azure CLI authentication. sp_env_auth (bool): Flag indicating whether to use application authentication with environment variables. + env_auth: (bool): Flag indicating whether to use application and PowerShell authentication with environment variables. browser_auth (bool): Flag indicating whether to use interactive browser authentication. - tenant_id (str): The Microsoft365 Active Directory tenant ID. - region (str): The Microsoft365 region. + tenant_id (str): The M365 Active Directory tenant ID. + region (str): The M365 region. raise_on_exception (bool): Flag indicating whether to raise an exception if the connection fails. - client_id (str): The Microsoft365 client ID. - client_secret (str): The Microsoft365 client secret. + client_id (str): The M365 client ID. + client_secret (str): The M365 client secret. + user (str): The M365 user email. + encrypted_password (str): The M365 encrypted_password. + Returns: bool: True if the connection is successful, False otherwise. Raises: - Exception: If failed to test the connection to Microsoft365 subscription. - Microsoft365ArgumentTypeValidationError: If there is an error in the argument type validation. - Microsoft365SetUpRegionConfigError: If there is an error in setting up the region configuration. - Microsoft365InteractiveBrowserCredentialError: If there is an error in retrieving the Microsoft365 credentials using browser authentication. - Microsoft365HTTPResponseError: If there is an HTTP response error. - Microsoft365ConfigCredentialsError: If there is an error in configuring the Microsoft365 credentials from a dictionary. + Exception: If failed to test the connection to M365 subscription. + M365ArgumentTypeValidationError: If there is an error in the argument type validation. + M365SetUpRegionConfigError: If there is an error in setting up the region configuration. + M365InteractiveBrowserCredentialError: If there is an error in retrieving the M365 credentials using browser authentication. + M365HTTPResponseError: If there is an HTTP response error. + M365ConfigCredentialsError: If there is an error in configuring the M365 credentials from a dictionary. Examples: - >>> Microsoft365Provider.test_connection(az_cli_auth=True) + >>> M365Provider.test_connection(az_cli_auth=True) True - >>> Microsoft365Provider.test_connection(sp_env_auth=False, browser_auth=True, tenant_id=None) - False, ArgumentTypeError: Microsoft365 Tenant ID is required only for browser authentication mode - >>> Microsoft365Provider.test_connection(tenant_id="XXXXXXXXXX", client_id="XXXXXXXXXX", client_secret="XXXXXXXXXX") + >>> M365Provider.test_connection(sp_env_auth=False, browser_auth=True, tenant_id=None) + False, ArgumentTypeError: M365 Tenant ID is required only for browser authentication mode + >>> M365Provider.test_connection(tenant_id="XXXXXXXXXX", client_id="XXXXXXXXXX", client_secret="XXXXXXXXXX") True """ try: - Microsoft365Provider.validate_arguments( + M365Provider.validate_arguments( az_cli_auth, sp_env_auth, + env_auth, browser_auth, tenant_id, client_id, client_secret, + user, + encrypted_password, ) - region_config = Microsoft365Provider.setup_region_config(region) + region_config = M365Provider.setup_region_config(region) # Get the dict from the static credentials - microsoft365_credentials = None + m365_credentials = None if tenant_id and client_id and client_secret: - microsoft365_credentials = ( - Microsoft365Provider.validate_static_credentials( - tenant_id=tenant_id, - client_id=client_id, - client_secret=client_secret, - ) + m365_credentials = M365Provider.validate_static_credentials( + tenant_id=tenant_id, + client_id=client_id, + client_secret=client_secret, ) - # Set up the Microsoft365 session - credentials = Microsoft365Provider.setup_session( + # Set up the M365 session + credentials = M365Provider.setup_session( az_cli_auth, sp_env_auth, + env_auth, browser_auth, tenant_id, - microsoft365_credentials, + m365_credentials, region_config, ) GraphServiceClient(credentials=credentials) - logger.info("Microsoft365 provider: Connection to Microsoft365 successful") + logger.info("M365 provider: Connection to M365 successful") return Connection(is_connected=True) # Exceptions from setup_region_config - except Microsoft365ArgumentTypeValidationError as type_validation_error: + except M365ArgumentTypeValidationError as type_validation_error: logger.error( f"{type_validation_error.__class__.__name__}[{type_validation_error.__traceback__.tb_lineno}]: {type_validation_error}" ) if raise_on_exception: raise type_validation_error return Connection(error=type_validation_error) - except Microsoft365SetUpRegionConfigError as region_config_error: + except M365SetUpRegionConfigError as region_config_error: logger.error( f"{region_config_error.__class__.__name__}[{region_config_error.__traceback__.tb_lineno}]: {region_config_error}" ) @@ -583,28 +688,28 @@ class Microsoft365Provider(Provider): raise region_config_error return Connection(error=region_config_error) # Exceptions from setup_session - except Microsoft365EnvironmentVariableError as environment_credentials_error: + except M365EnvironmentVariableError as environment_credentials_error: logger.error( f"{environment_credentials_error.__class__.__name__}[{environment_credentials_error.__traceback__.tb_lineno}]: {environment_credentials_error}" ) if raise_on_exception: raise environment_credentials_error return Connection(error=environment_credentials_error) - except Microsoft365ConfigCredentialsError as config_credentials_error: + except M365ConfigCredentialsError as config_credentials_error: logger.error( f"{config_credentials_error.__class__.__name__}[{config_credentials_error.__traceback__.tb_lineno}]: {config_credentials_error}" ) if raise_on_exception: raise config_credentials_error return Connection(error=config_credentials_error) - except Microsoft365ClientAuthenticationError as client_auth_error: + except M365ClientAuthenticationError as client_auth_error: logger.error( f"{client_auth_error.__class__.__name__}[{client_auth_error.__traceback__.tb_lineno}]: {client_auth_error}" ) if raise_on_exception: raise client_auth_error return Connection(error=client_auth_error) - except Microsoft365CredentialsUnavailableError as credential_unavailable_error: + except M365CredentialsUnavailableError as credential_unavailable_error: logger.error( f"{credential_unavailable_error.__class__.__name__}[{credential_unavailable_error.__traceback__.tb_lineno}]: {credential_unavailable_error}" ) @@ -612,7 +717,7 @@ class Microsoft365Provider(Provider): raise credential_unavailable_error return Connection(error=credential_unavailable_error) except ( - Microsoft365ClientIdAndClientSecretNotBelongingToTenantIdError + M365ClientIdAndClientSecretNotBelongingToTenantIdError ) as tenant_id_error: logger.error( f"{tenant_id_error.__class__.__name__}[{tenant_id_error.__traceback__.tb_lineno}]: {tenant_id_error}" @@ -621,7 +726,7 @@ class Microsoft365Provider(Provider): raise tenant_id_error return Connection(error=tenant_id_error) except ( - Microsoft365TenantIdAndClientSecretNotBelongingToClientIdError + M365TenantIdAndClientSecretNotBelongingToClientIdError ) as client_id_error: logger.error( f"{client_id_error.__class__.__name__}[{client_id_error.__traceback__.tb_lineno}]: {client_id_error}" @@ -630,7 +735,7 @@ class Microsoft365Provider(Provider): raise client_id_error return Connection(error=client_id_error) except ( - Microsoft365TenantIdAndClientIdNotBelongingToClientSecretError + M365TenantIdAndClientIdNotBelongingToClientSecretError ) as client_secret_error: logger.error( f"{client_secret_error.__class__.__name__}[{client_secret_error.__traceback__.tb_lineno}]: {client_secret_error}" @@ -639,7 +744,7 @@ class Microsoft365Provider(Provider): raise client_secret_error return Connection(error=client_secret_error) # Exceptions from provider_id validation - except Microsoft365InvalidProviderIdError as invalid_credentials_error: + except M365InvalidProviderIdError as invalid_credentials_error: logger.error( f"{invalid_credentials_error.__class__.__name__}[{invalid_credentials_error.__traceback__.tb_lineno}]: {invalid_credentials_error}" ) @@ -652,7 +757,7 @@ class Microsoft365Provider(Provider): f"{http_response_error.__class__.__name__}[{http_response_error.__traceback__.tb_lineno}]: {http_response_error}" ) if raise_on_exception: - raise Microsoft365HTTPResponseError( + raise M365HTTPResponseError( file=os.path.basename(__file__), original_exception=http_response_error, ) @@ -679,14 +784,14 @@ class Microsoft365Provider(Provider): If any of the environment variables is missing, it logs a critical error and exits the program. """ logger.info( - "Microsoft365 provider: checking service principal environment variables ..." + "M365 provider: checking service principal environment variables ..." ) for env_var in ["AZURE_CLIENT_ID", "AZURE_TENANT_ID", "AZURE_CLIENT_SECRET"]: if not getenv(env_var): logger.critical( - f"Microsoft365 provider: Missing environment variable {env_var} needed to authenticate against Microsoft365" + f"M365 provider: Missing environment variable {env_var} needed to authenticate against M365." ) - raise Microsoft365EnvironmentVariableError( + raise M365EnvironmentVariableError( file=os.path.basename(__file__), message=f"Missing environment variable {env_var} required to authenticate.", ) @@ -695,32 +800,34 @@ class Microsoft365Provider(Provider): self, az_cli_auth, sp_env_auth, + env_auth, browser_auth, client_id, ): """ - Sets up the identity for the Microsoft365 provider. + Sets up the identity for the M365 provider. Args: az_cli_auth (bool): Flag indicating if Azure CLI authentication is used. sp_env_auth (bool): Flag indicating if application authentication with environment variables is used. + env_auth: (bool): Flag indicating whether to use application and PowerShell authentication with environment variables. browser_auth (bool): Flag indicating if interactive browser authentication is used. - client_id (str): The Microsoft365 client ID. + client_id (str): The M365 client ID. Returns: - Microsoft365IdentityInfo: An instance of Microsoft365IdentityInfo containing the identity information. + M365IdentityInfo: An instance of M365IdentityInfo containing the identity information. """ credentials = self.session # TODO: fill this object with real values not default and set to none - identity = Microsoft365IdentityInfo() + identity = M365IdentityInfo() # If credentials comes from service principal or browser, if the required permissions are assigned # the identity can access AAD and retrieve the tenant domain name. - # With cli also should be possible but right now it does not work, microsoft365 python package issue is coming + # With cli also should be possible but right now it does not work, m365 python package issue is coming # At the time of writting this with az cli creds is not working, despite that is included - if az_cli_auth or sp_env_auth or browser_auth or client_id: + if env_auth or az_cli_auth or sp_env_auth or browser_auth or client_id: - async def get_microsoft365_identity(): + async def get_m365_identity(): # Trying to recover tenant domain info try: logger.info( @@ -737,7 +844,7 @@ class Microsoft365Provider(Provider): logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365HTTPResponseError( + raise M365HTTPResponseError( file=os.path.basename(__file__), original_exception=error, ) @@ -745,7 +852,7 @@ class Microsoft365Provider(Provider): logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) - raise Microsoft365GetTokenIdentityError( + raise M365GetTokenIdentityError( file=os.path.basename(__file__), original_exception=error, ) @@ -754,7 +861,7 @@ class Microsoft365Provider(Provider): f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" ) # since that exception is not considered as critical, we keep filling another identity fields - if sp_env_auth or client_id: + if sp_env_auth or env_auth or client_id: # The id of the sp can be retrieved from environment variables identity.identity_id = getenv("AZURE_CLIENT_ID") identity.identity_type = "Service Principal" @@ -784,7 +891,7 @@ class Microsoft365Provider(Provider): organization_info = await client.organization.get() identity.tenant_id = organization_info.value[0].id - asyncio.get_event_loop().run_until_complete(get_microsoft365_identity()) + asyncio.get_event_loop().run_until_complete(get_m365_identity()) return identity @staticmethod @@ -792,20 +899,20 @@ class Microsoft365Provider(Provider): tenant_id: str = None, client_id: str = None, client_secret: str = None ) -> dict: """ - Validates the static credentials for the Microsoft365 provider. + Validates the static credentials for the M365 provider. Args: - tenant_id (str): The Microsoft365 Active Directory tenant ID. - client_id (str): The Microsoft365 client ID. - client_secret (str): The Microsoft365 client secret. + tenant_id (str): The M365 Active Directory tenant ID. + client_id (str): The M365 client ID. + client_secret (str): The M365 client secret. Raises: - Microsoft365NotValidTenantIdError: If the provided Microsoft365 Tenant ID is not valid. - Microsoft365NotValidClientIdError: If the provided Microsoft365 Client ID is not valid. - Microsoft365NotValidClientSecretError: If the provided Microsoft365 Client Secret is not valid. - Microsoft365ClientIdAndClientSecretNotBelongingToTenantIdError: If the provided Microsoft365 Client ID and Client Secret do not belong to the specified Tenant ID. - Microsoft365TenantIdAndClientSecretNotBelongingToClientIdError: If the provided Microsoft365 Tenant ID and Client Secret do not belong to the specified Client ID. - Microsoft365TenantIdAndClientIdNotBelongingToClientSecretError: If the provided Microsoft365 Tenant ID and Client ID do not belong to the specified Client Secret. + M365NotValidTenantIdError: If the provided M365 Tenant ID is not valid. + M365NotValidClientIdError: If the provided M365 Client ID is not valid. + M365NotValidClientSecretError: If the provided M365 Client Secret is not valid. + M365ClientIdAndClientSecretNotBelongingToTenantIdError: If the provided M365 Client ID and Client Secret do not belong to the specified Tenant ID. + M365TenantIdAndClientSecretNotBelongingToClientIdError: If the provided M365 Tenant ID and Client Secret do not belong to the specified Client ID. + M365TenantIdAndClientIdNotBelongingToClientSecretError: If the provided M365 Tenant ID and Client ID do not belong to the specified Client Secret. Returns: dict: A dictionary containing the validated static credentials. @@ -814,72 +921,72 @@ class Microsoft365Provider(Provider): try: UUID(tenant_id) except ValueError: - raise Microsoft365NotValidTenantIdError( + raise M365NotValidTenantIdError( file=os.path.basename(__file__), - message="The provided Microsoft365 Tenant ID is not valid.", + message="The provided M365 Tenant ID is not valid.", ) # Validate the Client ID try: UUID(client_id) except ValueError: - raise Microsoft365NotValidClientIdError( + raise M365NotValidClientIdError( file=os.path.basename(__file__), - message="The provided Microsoft365 Client ID is not valid.", + message="The provided M365 Client ID is not valid.", ) # Validate the Client Secret if not re.match("^[a-zA-Z0-9._~-]+$", client_secret): - raise Microsoft365NotValidClientSecretError( + raise M365NotValidClientSecretError( file=os.path.basename(__file__), - message="The provided Microsoft365 Client Secret is not valid.", + message="The provided M365 Client Secret is not valid.", ) try: - Microsoft365Provider.verify_client(tenant_id, client_id, client_secret) + M365Provider.verify_client(tenant_id, client_id, client_secret) return { "tenant_id": tenant_id, "client_id": client_id, "client_secret": client_secret, } - except Microsoft365NotValidTenantIdError as tenant_id_error: + except M365NotValidTenantIdError as tenant_id_error: logger.error( f"{tenant_id_error.__class__.__name__}[{tenant_id_error.__traceback__.tb_lineno}]: {tenant_id_error}" ) - raise Microsoft365ClientIdAndClientSecretNotBelongingToTenantIdError( + raise M365ClientIdAndClientSecretNotBelongingToTenantIdError( file=os.path.basename(__file__), - message="The provided Microsoft365 Client ID and Client Secret do not belong to the specified Tenant ID.", + message="The provided M365 Client ID and Client Secret do not belong to the specified Tenant ID.", ) - except Microsoft365NotValidClientIdError as client_id_error: + except M365NotValidClientIdError as client_id_error: logger.error( f"{client_id_error.__class__.__name__}[{client_id_error.__traceback__.tb_lineno}]: {client_id_error}" ) - raise Microsoft365TenantIdAndClientSecretNotBelongingToClientIdError( + raise M365TenantIdAndClientSecretNotBelongingToClientIdError( file=os.path.basename(__file__), - message="The provided Microsoft365 Tenant ID and Client Secret do not belong to the specified Client ID.", + message="The provided M365 Tenant ID and Client Secret do not belong to the specified Client ID.", ) - except Microsoft365NotValidClientSecretError as client_secret_error: + except M365NotValidClientSecretError as client_secret_error: logger.error( f"{client_secret_error.__class__.__name__}[{client_secret_error.__traceback__.tb_lineno}]: {client_secret_error}" ) - raise Microsoft365TenantIdAndClientIdNotBelongingToClientSecretError( + raise M365TenantIdAndClientIdNotBelongingToClientSecretError( file=os.path.basename(__file__), - message="The provided Microsoft365 Tenant ID and Client ID do not belong to the specified Client Secret.", + message="The provided M365 Tenant ID and Client ID do not belong to the specified Client Secret.", ) @staticmethod def verify_client(tenant_id, client_id, client_secret) -> None: """ - Verifies the Microsoft365 client credentials using the specified tenant ID, client ID, and client secret. + Verifies the M365 client credentials using the specified tenant ID, client ID, and client secret. Args: - tenant_id (str): The Microsoft365 Active Directory tenant ID. - client_id (str): The Microsoft365 client ID. - client_secret (str): The Microsoft365 client secret. + tenant_id (str): The M365 Active Directory tenant ID. + client_id (str): The M365 client ID. + client_secret (str): The M365 client secret. Raises: - Microsoft365NotValidTenantIdError: If the provided Microsoft365 Tenant ID is not valid. - Microsoft365NotValidClientIdError: If the provided Microsoft365 Client ID is not valid. - Microsoft365NotValidClientSecretError: If the provided Microsoft365 Client Secret is not valid. + M365NotValidTenantIdError: If the provided M365 Tenant ID is not valid. + M365NotValidClientIdError: If the provided M365 Client ID is not valid. + M365NotValidClientSecretError: If the provided M365 Client Secret is not valid. Returns: None @@ -903,17 +1010,17 @@ class Microsoft365Provider(Provider): # Handle specific errors based on the MSAL response error_description = result.get("error_description", "") if f"Tenant '{tenant_id}'" in error_description: - raise Microsoft365NotValidTenantIdError( + raise M365NotValidTenantIdError( file=os.path.basename(__file__), message="The provided Microsoft 365 Tenant ID is not valid for the specified Client ID and Client Secret.", ) if f"Application with identifier '{client_id}'" in error_description: - raise Microsoft365NotValidClientIdError( + raise M365NotValidClientIdError( file=os.path.basename(__file__), message="The provided Microsoft 365 Client ID is not valid for the specified Tenant ID and Client Secret.", ) if "Invalid client secret provided" in error_description: - raise Microsoft365NotValidClientSecretError( + raise M365NotValidClientSecretError( file=os.path.basename(__file__), message="The provided Microsoft 365 Client Secret is not valid for the specified Tenant ID and Client ID.", ) diff --git a/prowler/providers/microsoft365/models.py b/prowler/providers/m365/models.py similarity index 83% rename from prowler/providers/microsoft365/models.py rename to prowler/providers/m365/models.py index c1e028e8d6..f260653555 100644 --- a/prowler/providers/microsoft365/models.py +++ b/prowler/providers/m365/models.py @@ -4,7 +4,7 @@ from prowler.config.config import output_file_timestamp from prowler.providers.common.models import ProviderOutputOptions -class Microsoft365IdentityInfo(BaseModel): +class M365IdentityInfo(BaseModel): identity_id: str = "" identity_type: str = "" tenant_id: str = "" @@ -12,14 +12,22 @@ class Microsoft365IdentityInfo(BaseModel): location: str = "" -class Microsoft365RegionConfig(BaseModel): +class M365RegionConfig(BaseModel): name: str = "" authority: str = None base_url: str = "" credential_scopes: list = [] -class Microsoft365OutputOptions(ProviderOutputOptions): +class M365Credentials(BaseModel): + user: str = "" + passwd: str = "" + client_id: str = "" + client_secret: str = "" + tenant_id: str = "" + + +class M365OutputOptions(ProviderOutputOptions): def __init__(self, arguments, bulk_checks_metadata, identity): # First call Provider_Output_Options init super().__init__(arguments, bulk_checks_metadata) diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/__init__.py b/prowler/providers/m365/services/admincenter/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/__init__.py rename to prowler/providers/m365/services/admincenter/__init__.py diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_client.py b/prowler/providers/m365/services/admincenter/admincenter_client.py similarity index 53% rename from prowler/providers/microsoft365/services/admincenter/admincenter_client.py rename to prowler/providers/m365/services/admincenter/admincenter_client.py index 72facdeefd..a1e3341296 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_client.py +++ b/prowler/providers/m365/services/admincenter/admincenter_client.py @@ -1,6 +1,4 @@ from prowler.providers.common.provider import Provider -from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( - AdminCenter, -) +from prowler.providers.m365.services.admincenter.admincenter_service import AdminCenter admincenter_client = AdminCenter(Provider.get_global_provider()) diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/__init__.py b/prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/__init__.py rename to prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/__init__.py diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.metadata.json b/prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.metadata.json rename to prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.metadata.json index 733298af55..f703c3b594 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.metadata.json +++ b/prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "admincenter_groups_not_public_visibility", "CheckTitle": "Ensure that only organizationally managed/approved public groups exist", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.py b/prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.py similarity index 79% rename from prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.py rename to prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.py index 884d614612..d61fdec68d 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.py +++ b/prowler/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.admincenter.admincenter_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.admincenter.admincenter_client import ( admincenter_client, ) @@ -16,18 +16,18 @@ class admincenter_groups_not_public_visibility(Check): metadata: Metadata associated with the check (inherited from Check). """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check for groups with public visibility. This method iterates through all groups in Microsoft Admin Center and checks if any group has 'Public' visibility. If so, the check fails for that group. Returns: - List[CheckReportMicrosoft365]: A list containing the results of the check for each group. + List[CheckReportM365]: A list containing the results of the check for each group. """ findings = [] for group in admincenter_client.groups.values(): - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=group, resource_name=group.name, diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_service.py b/prowler/providers/m365/services/admincenter/admincenter_service.py similarity index 91% rename from prowler/providers/microsoft365/services/admincenter/admincenter_service.py rename to prowler/providers/m365/services/admincenter/admincenter_service.py index fed450ca82..723c7644d1 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_service.py +++ b/prowler/providers/m365/services/admincenter/admincenter_service.py @@ -5,12 +5,12 @@ from msgraph.generated.models.o_data_errors.o_data_error import ODataError from pydantic import BaseModel from prowler.lib.logger import logger -from prowler.providers.microsoft365.lib.service.service import Microsoft365Service -from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider +from prowler.providers.m365.lib.service.service import M365Service +from prowler.providers.m365.m365_provider import M365Provider -class AdminCenter(Microsoft365Service): - def __init__(self, provider: Microsoft365Provider): +class AdminCenter(M365Service): + def __init__(self, provider: M365Provider): super().__init__(provider) loop = get_event_loop() @@ -31,7 +31,7 @@ class AdminCenter(Microsoft365Service): self.domains = attributes[2] async def _get_users(self): - logger.info("Microsoft365 - Getting users...") + logger.info("M365 - Getting users...") users = {} try: users_list = await self.client.users.get() @@ -75,7 +75,7 @@ class AdminCenter(Microsoft365Service): return users async def _get_directory_roles(self): - logger.info("Microsoft365 - Getting directory roles...") + logger.info("M365 - Getting directory roles...") directory_roles_with_members = {} try: directory_roles_with_members.update({}) @@ -110,7 +110,7 @@ class AdminCenter(Microsoft365Service): return directory_roles_with_members async def _get_groups(self): - logger.info("Microsoft365 - Getting groups...") + logger.info("M365 - Getting groups...") groups = {} try: groups_list = await self.client.groups.get() @@ -133,7 +133,7 @@ class AdminCenter(Microsoft365Service): return groups async def _get_domains(self): - logger.info("Microsoft365 - Getting domains...") + logger.info("M365 - Getting domains...") domains = {} try: domains_list = await self.client.domains.get() diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/__init__.py b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/__init__.py rename to prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/__init__.py diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.metadata.json b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.metadata.json rename to prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.metadata.json index a79fc45e94..20ae0d55c0 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.metadata.json +++ b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "admincenter_settings_password_never_expire", "CheckTitle": "Ensure the 'Password expiration policy' is set to 'Set passwords to never expire (recommended)'", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py similarity index 81% rename from prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py rename to prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py index fa1ff62265..4af24427ea 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py +++ b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.admincenter.admincenter_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.admincenter.admincenter_client import ( admincenter_client, ) @@ -17,19 +17,19 @@ class admincenter_settings_password_never_expire(Check): metadata: Metadata associated with the check (inherited from Check). """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check for password never expires policy. This method iterates over all domains and checks if the password validity period is set to `2147483647`, indicating that passwords for users in the domain never expire. Returns: - List[CheckReportMicrosoft365]: A list of reports indicating whether the domain's password + List[CheckReportM365]: A list of reports indicating whether the domain's password policy is set to never expire. """ findings = [] for domain in admincenter_client.domains.values(): - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=domain, resource_name=domain.id, diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/__init__.py b/prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/__init__.py rename to prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/__init__.py diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.metadata.json b/prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.metadata.json rename to prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.metadata.json index 563dd09157..e39c14ca71 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.metadata.json +++ b/prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "admincenter_users_admins_reduced_license_footprint", "CheckTitle": "Ensure administrative accounts use licenses with a reduced application footprint", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.py b/prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.py similarity index 86% rename from prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.py rename to prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.py index 9d57e3cbc2..7497feb305 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.py +++ b/prowler/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.admincenter.admincenter_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.admincenter.admincenter_client import ( admincenter_client, ) @@ -17,7 +17,7 @@ class admincenter_users_admins_reduced_license_footprint(Check): metadata: Metadata associated with the check (inherited from Check). """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check for users with administrative roles and their licenses. This method iterates over all users and checks if those with administrative roles @@ -25,7 +25,7 @@ class admincenter_users_admins_reduced_license_footprint(Check): the check passes; otherwise, it fails. Returns: - List[CheckReportMicrosoft365]: A list containing the result of the check for each user. + List[CheckReportM365]: A list containing the result of the check for each user. """ findings = [] allowed_licenses = ["AAD_PREMIUM", "AAD_PREMIUM_P2"] @@ -39,7 +39,7 @@ class admincenter_users_admins_reduced_license_footprint(Check): ) if admin_roles: - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=user, resource_name=user.name, diff --git a/prowler/providers/microsoft365/services/entra/__init__.py b/prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/__init__.py rename to prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/__init__.py diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.metadata.json b/prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.metadata.json rename to prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.metadata.json index 2ffc185f91..8591295973 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.metadata.json +++ b/prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "admincenter_users_between_two_and_four_global_admins", "CheckTitle": "Ensure that between two and four global admins are designated", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.py b/prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.py similarity index 83% rename from prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.py rename to prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.py index 0abebdce31..d584bc8a32 100644 --- a/prowler/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.py +++ b/prowler/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.admincenter.admincenter_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.admincenter.admincenter_client import ( admincenter_client, ) @@ -16,21 +16,21 @@ class admincenter_users_between_two_and_four_global_admins(Check): metadata: Metadata associated with the check (inherited from Check). """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check for the number of Global Administrators. This method checks if the number of users with the 'Global Administrator' role is between two and four. If the condition is met, the check passes; otherwise, it fails. Returns: - List[CheckReportMicrosoft365]: A list containing the result of the check for the Global Administrators. + List[CheckReportM365]: A list containing the result of the check for the Global Administrators. """ findings = [] directory_roles = admincenter_client.directory_roles global_admin_role = directory_roles.get("Global Administrator", {}) if global_admin_role: - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=global_admin_role, resource_name=global_admin_role.name, diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/__init__.py b/prowler/providers/m365/services/entra/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/__init__.py rename to prowler/providers/m365/services/entra/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/__init__.py b/prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/__init__.py rename to prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.metadata.json index a70b98501a..ef4f550307 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_admin_consent_workflow_enabled", "CheckTitle": "Ensure the admin consent workflow is enabled.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.py b/prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.py similarity index 86% rename from prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.py rename to prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.py index 24bcbe9c47..5a22c343ce 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.py +++ b/prowler/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client class entra_admin_consent_workflow_enabled(Check): @@ -17,7 +17,7 @@ class entra_admin_consent_workflow_enabled(Check): from accessing critical applications or forced to use insecure workarounds. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the admin consent workflow requirement check. @@ -25,12 +25,12 @@ class entra_admin_consent_workflow_enabled(Check): whether the admin consent workflow is enabled. Returns: - List[CheckReportMicrosoft365]: A list containing the report with the result of the check. + List[CheckReportM365]: A list containing the report with the result of the check. """ findings = [] admin_consent_policy = entra_client.admin_consent_policy if admin_consent_policy: - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=admin_consent_policy, resource_name="Admin Consent Policy", diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/__init__.py b/prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/__init__.py rename to prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.metadata.json b/prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.metadata.json rename to prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.metadata.json index 41ba6ba9ce..06f70fcba4 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.metadata.json +++ b/prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_admin_portals_access_restriction", "CheckTitle": "Ensure that only administrative roles have access to Microsoft Admin Portals", "CheckAliases": [ diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.py b/prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.py similarity index 84% rename from prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.py rename to prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.py index a8f744ec4a..23f6e3288a 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.py +++ b/prowler/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( AdminRoles, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -13,15 +13,15 @@ class entra_admin_portals_access_restriction(Check): This check ensures that Conditional Access policies are in place to deny access to the Microsoft 365 admin center for users with limited access roles. """ - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that Conditional Access policies deny access to the Microsoft 365 admin center for users with limited access roles. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -52,7 +52,7 @@ class entra_admin_portals_access_restriction(Check): ConditionalAccessGrantControl.BLOCK in policy.grant_controls.built_in_controls ): - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_admin_users_cloud_only/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_admin_users_cloud_only/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.metadata.json b/prowler/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.metadata.json similarity index 81% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.metadata.json rename to prowler/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.metadata.json index e507677a0d..4e7a5f4574 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.metadata.json +++ b/prowler/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_admin_users_cloud_only", "CheckTitle": "Ensure all Microsoft 365 administrative users are cloud-only", "CheckType": [], @@ -15,7 +15,7 @@ "Code": { "CLI": "", "NativeIaC": "", - "Other": "1. Identify on-premises synchronized administrative users using Microsoft Entra Connect or equivalent tools.\n2. Create new cloud-only administrative user with appropriate permissions.\n3. Migrate administrative tasks from on-premises synchronized users to the new cloud-only user.\n4. Disable or remove the on-premises synchronized administrative users.", + "Other": "1. Identify on-premises synchronized administrative users using Microsoft Entra Connect or equivalent tools. 2. Create new cloud-only administrative user with appropriate permissions. 3. Migrate administrative tasks from on-premises synchronized users to the new cloud-only user. 4. Disable or remove the on-premises synchronized administrative users.", "Terraform": "" }, "Recommendation": { diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.py b/prowler/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.py similarity index 78% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.py rename to prowler/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.py index 7ea617ca0e..c41699337c 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.py +++ b/prowler/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only.py @@ -1,8 +1,8 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import AdminRoles +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import AdminRoles class entra_admin_users_cloud_only(Check): @@ -12,11 +12,11 @@ class entra_admin_users_cloud_only(Check): If such users are found, the check will fail. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the check to identify admin accounts with non-cloud-only accounts. Returns: - List[CheckReportMicrosoft365]: A list containing the check report with the status and details. + List[CheckReportM365]: A list containing the check report with the status and details. """ findings = [] if entra_client.users: @@ -29,7 +29,7 @@ class entra_admin_users_cloud_only(Check): ): non_cloud_admins.append(user_id) - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Cloud-only account", diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.metadata.json index 63f312be10..84f12d6b48 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_admin_users_mfa_enabled", "CheckTitle": "Ensure multifactor authentication is enabled for all users in administrative roles.", "CheckAliases": [ diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.py b/prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.py similarity index 85% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.py rename to prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.py index e668ffd11a..dff536999b 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.py +++ b/prowler/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled.py @@ -1,8 +1,8 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( AdminRoles, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -20,7 +20,7 @@ class entra_admin_users_mfa_enabled(Check): The check fails if no enabled policy is found that requires MFA for any administrative role. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the admin MFA requirement check for administrative roles. @@ -28,11 +28,11 @@ class entra_admin_users_mfa_enabled(Check): indicating whether MFA is enforced for users in administrative roles. Returns: - List[CheckReportMicrosoft365]: A list containing a single report with the result of the check. + List[CheckReportM365]: A list containing a single report with the result of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -62,7 +62,7 @@ class entra_admin_users_mfa_enabled(Check): ConditionalAccessGrantControl.MFA in policy.grant_controls.built_in_controls ): - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=entra_client.conditional_access_policies, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.metadata.json index 3aacb2c1ac..0865121916 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_admin_users_phishing_resistant_mfa_enabled", "CheckTitle": "Ensure phishing-resistant MFA strength is required for all administrator accounts", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.py b/prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.py similarity index 84% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.py rename to prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.py index 97022161f7..6f0fbc281d 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.py +++ b/prowler/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( AdminRoles, AuthenticationStrength, ConditionalAccessPolicyState, @@ -10,14 +10,14 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( class entra_admin_users_phishing_resistant_mfa_enabled(Check): """Check if Conditional Access policies require Phishing-resistant MFA strength for admin users.""" - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that Conditional Access policies require Phishing-resistant MFA strength for admin users. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -49,7 +49,7 @@ class entra_admin_users_phishing_resistant_mfa_enabled(Check): and policy.grant_controls.authentication_strength == AuthenticationStrength.PHISHING_RESISTANT_MFA ): - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/__init__.py b/prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/__init__.py rename to prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.metadata.json index c7dd5caa40..859e15dabc 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_admin_users_sign_in_frequency_enabled", "CheckTitle": "Ensure Sign-in frequency periodic reauthentication is enabled and properly configured.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.py b/prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.py similarity index 91% rename from prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.py rename to prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.py index 38558fc0f3..3e63d16f32 100644 --- a/prowler/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.py +++ b/prowler/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( AdminRoles, ConditionalAccessPolicyState, SignInFrequencyInterval, @@ -11,10 +11,10 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( class entra_admin_users_sign_in_frequency_enabled(Check): """Check if Conditional Access policies enforce sign-in frequency for admin users.""" - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Validate sign-in frequency enforcement for admin users.""" findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -40,7 +40,7 @@ class entra_admin_users_sign_in_frequency_enabled(Check): ): continue - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_client.py b/prowler/providers/m365/services/entra/entra_client.py similarity index 58% rename from prowler/providers/microsoft365/services/entra/entra_client.py rename to prowler/providers/m365/services/entra/entra_client.py index 1a3b921adf..84c60b40fd 100644 --- a/prowler/providers/microsoft365/services/entra/entra_client.py +++ b/prowler/providers/m365/services/entra/entra_client.py @@ -1,4 +1,4 @@ from prowler.providers.common.provider import Provider -from prowler.providers.microsoft365.services.entra.entra_service import Entra +from prowler.providers.m365.services.entra.entra_service import Entra entra_client = Entra(Provider.get_global_provider()) diff --git a/prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.metadata.json b/prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.metadata.json rename to prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.metadata.json index 55c2916196..efa0c5b6dc 100644 --- a/prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.metadata.json +++ b/prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_dynamic_group_for_guests_created", "CheckTitle": "Ensure a dynamic group for guest users is created.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.py b/prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.py similarity index 84% rename from prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.py rename to prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.py index 9bd70f624c..f4ba9ff616 100644 --- a/prowler/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.py +++ b/prowler/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client class entra_dynamic_group_for_guests_created(Check): @@ -14,7 +14,7 @@ class entra_dynamic_group_for_guests_created(Check): automated enforcement of conditional access policies and reduces manual management of guest access. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the dynamic group for guest users check. @@ -22,7 +22,7 @@ class entra_dynamic_group_for_guests_created(Check): indicating whether at least one dynamic group exists with a membership rule targeting guest users. Returns: - List[CheckReportMicrosoft365]: A list containing a single report with the result of the check. + List[CheckReportM365]: A list containing a single report with the result of the check. """ findings = [] if entra_client.groups: @@ -33,7 +33,7 @@ class entra_dynamic_group_for_guests_created(Check): dynamic_group = group break - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=dynamic_group if dynamic_group else {}, resource_name=dynamic_group.name if dynamic_group else "Group", diff --git a/prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.metadata.json index 039071202c..bb524cfb98 100644 --- a/prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_identity_protection_sign_in_risk_enabled", "CheckTitle": "Ensure that Identity Protection sign-in risk policies are enabled", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.py b/prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.py similarity index 86% rename from prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.py rename to prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.py index 29b33cdc3e..c9878c8315 100644 --- a/prowler/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.py +++ b/prowler/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessGrantControl, ConditionalAccessPolicyState, RiskLevel, @@ -14,15 +14,15 @@ class entra_identity_protection_sign_in_risk_enabled(Check): This check ensures that at least one Conditional Access policy is a Identity Protection sign-in risk policy. """ - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that at least one Conditional Access policy is a Identity Protection sign-in risk policy. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -56,7 +56,7 @@ class entra_identity_protection_sign_in_risk_enabled(Check): ): continue - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/__init__.py b/prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/__init__.py rename to prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.metadata.json index 04f94276b9..a36bec74f9 100644 --- a/prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_identity_protection_user_risk_enabled", "CheckTitle": "Ensure that Identity Protection user risk policies are enabled", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.py b/prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.py similarity index 86% rename from prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.py rename to prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.py index f6cb547474..8864663e68 100644 --- a/prowler/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.py +++ b/prowler/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessGrantControl, ConditionalAccessPolicyState, GrantControlOperator, @@ -14,15 +14,15 @@ class entra_identity_protection_user_risk_enabled(Check): This check ensures that at least one Conditional Access policy is a Identity Protection user risk policy. """ - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that at least one Conditional Access policy is a Identity Protection user risk policy. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -54,7 +54,7 @@ class entra_identity_protection_user_risk_enabled(Check): continue if policy.conditions.user_risk_levels: - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/__init__.py b/prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/__init__.py rename to prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.metadata.json b/prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.metadata.json rename to prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.metadata.json index 31ab36f686..eb4783c8ae 100644 --- a/prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.metadata.json +++ b/prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_legacy_authentication_blocked", "CheckTitle": "Ensure that Conditional Access policy blocks legacy authentication", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.py b/prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.py similarity index 84% rename from prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.py rename to prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.py index ee14720618..f625cb6182 100644 --- a/prowler/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.py +++ b/prowler/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( ClientAppType, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -13,14 +13,14 @@ class entra_legacy_authentication_blocked(Check): This check ensures that at least one Conditional Access policy blocks legacy authentication. """ - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that at least one Conditional Access policy blocks legacy authentication. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -55,7 +55,7 @@ class entra_legacy_authentication_blocked(Check): ConditionalAccessGrantControl.BLOCK in policy.grant_controls.built_in_controls ): - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/__init__.py b/prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/__init__.py rename to prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.metadata.json b/prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.metadata.json rename to prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.metadata.json index abaf961476..3f97198061 100644 --- a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.metadata.json +++ b/prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_managed_device_required_for_authentication", "CheckTitle": "Ensure that only managed devices are required for authentication", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.py b/prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.py similarity index 84% rename from prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.py rename to prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.py index 6825725a52..c8a8845bd9 100644 --- a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.py +++ b/prowler/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessGrantControl, ConditionalAccessPolicyState, GrantControlOperator, @@ -13,15 +13,15 @@ class entra_managed_device_required_for_authentication(Check): This check ensures that Conditional Access policies are in place to enforce managed device requirement for authentication. """ - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that Conditional Access policies enforce managed device requirement for authentication. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -54,7 +54,7 @@ class entra_managed_device_required_for_authentication(Check): continue if policy.grant_controls.operator == GrantControlOperator.OR: - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.metadata.json b/prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.metadata.json rename to prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.metadata.json index 871d9f318e..59d2e46d82 100644 --- a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.metadata.json +++ b/prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_managed_device_required_for_mfa_registration", "CheckTitle": "Ensure that only managed devices are required for MFA registration", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.py b/prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.py similarity index 84% rename from prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.py rename to prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.py index 7fc446c956..ee5336a4fd 100644 --- a/prowler/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.py +++ b/prowler/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration.py @@ -1,6 +1,6 @@ -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessGrantControl, ConditionalAccessPolicyState, GrantControlOperator, @@ -14,15 +14,15 @@ class entra_managed_device_required_for_mfa_registration(Check): This check ensures that Conditional Access policies are in place to enforce MFA registration on a managed device. """ - def execute(self) -> list[CheckReportMicrosoft365]: + def execute(self) -> list[CheckReportM365]: """Execute the check to ensure that Conditional Access policies enforce MFA registration on a managed device. Returns: - list[CheckReportMicrosoft365]: A list containing the results of the check. + list[CheckReportM365]: A list containing the results of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -53,7 +53,7 @@ class entra_managed_device_required_for_mfa_registration(Check): continue if policy.grant_controls.operator == GrantControlOperator.OR: - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=policy, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/__init__.py b/prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/__init__.py rename to prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.metadata.json index 9966b06066..373e44f042 100644 --- a/prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_password_hash_sync_enabled", "CheckTitle": "Ensure that password hash sync is enabled for hybrid deployments.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.py b/prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.py similarity index 82% rename from prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.py rename to prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.py index 57d4868fc3..25ece6283d 100644 --- a/prowler/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.py +++ b/prowler/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client class entra_password_hash_sync_enabled(Check): @@ -16,7 +16,7 @@ class entra_password_hash_sync_enabled(Check): Note: This control applies only to hybrid deployments using Microsoft Entra Connect sync and does not apply to federated domains. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the password hash synchronization requirement check. @@ -24,11 +24,11 @@ class entra_password_hash_sync_enabled(Check): password hash synchronization is enabled. Returns: - List[CheckReportMicrosoft365]: A list containing the report object with the result of the check. + List[CheckReportM365]: A list containing the report object with the result of the check. """ findings = [] for organization in entra_client.organizations: - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=organization, resource_id=organization.id, diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/__init__.py b/prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/__init__.py rename to prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.metadata.json b/prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.metadata.json rename to prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.metadata.json index df7e7f30db..47a1658322 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.metadata.json +++ b/prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_policy_ensure_default_user_cannot_create_tenants", "CheckTitle": "Ensure that 'Restrict non-admin users from creating tenants' is set to 'Yes'", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.py b/prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.py similarity index 82% rename from prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.py rename to prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.py index de2c2112eb..4a8c822b48 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.py +++ b/prowler/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/entra_policy_ensure_default_user_cannot_create_tenants.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client class entra_policy_ensure_default_user_cannot_create_tenants(Check): @@ -14,7 +14,7 @@ class entra_policy_ensure_default_user_cannot_create_tenants(Check): metadata: Metadata associated with the check (inherited from Check). """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check for tenant creation restrictions. This method examines the authorization policy settings to determine if @@ -22,12 +22,12 @@ class entra_policy_ensure_default_user_cannot_create_tenants(Check): restricted, the check passes. Returns: - List[Check_Report_Microsoft365]: A list containing the result of the check. + List[Check_Report_M365]: A list containing the result of the check. """ findings = [] auth_policy = entra_client.authorization_policy - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=auth_policy if auth_policy else {}, resource_name=auth_policy.name if auth_policy else "Authorization Policy", diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/__init__.py b/prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/__init__.py rename to prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.metadata.json b/prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.metadata.json rename to prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.metadata.json index ffd4e74d5e..9e77161921 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.metadata.json +++ b/prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_policy_guest_invite_only_for_admin_roles", "CheckTitle": "Ensure that 'Guest invite restrictions' is set to 'Only users assigned to specific admin roles can invite guest users'", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.py b/prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.py similarity index 80% rename from prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.py rename to prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.py index 6dfb7b5e36..710b5c524d 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.py +++ b/prowler/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/entra_policy_guest_invite_only_for_admin_roles.py @@ -1,8 +1,8 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import InvitationsFrom +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import InvitationsFrom class entra_policy_guest_invite_only_for_admin_roles(Check): @@ -13,7 +13,7 @@ class entra_policy_guest_invite_only_for_admin_roles(Check): are limited accordingly. Otherwise, they are not restricted. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the guest invitation restriction check. @@ -22,13 +22,13 @@ class entra_policy_guest_invite_only_for_admin_roles(Check): specific administrative roles only. Returns: - List[CheckReportMicrosoft365]: A list containing a single check report that + List[CheckReportM365]: A list containing a single check report that details the pass/fail status and description. """ findings = [] auth_policy = entra_client.authorization_policy - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=auth_policy if auth_policy else {}, resource_name=auth_policy.name if auth_policy else "Authorization Policy", diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/__init__.py b/prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/__init__.py rename to prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.metadata.json b/prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.metadata.json rename to prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.metadata.json index 06445080c7..c6482d6883 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.metadata.json +++ b/prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_policy_guest_users_access_restrictions", "CheckTitle": "Ensure That 'Guest users access restrictions' is set to 'Guest user access is restricted to properties and memberships of their own directory objects'", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.py b/prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.py similarity index 79% rename from prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.py rename to prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.py index 2e431c0cd9..8669135970 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.py +++ b/prowler/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/entra_policy_guest_users_access_restrictions.py @@ -1,8 +1,8 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import AuthPolicyRoles +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import AuthPolicyRoles class entra_policy_guest_users_access_restrictions(Check): @@ -12,22 +12,22 @@ class entra_policy_guest_users_access_restrictions(Check): are limited to accessing only the properties and memberships of their own directory objects. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the guest user access restriction check. - This method retrieves the authorization policy from the Microsoft365 Entra client, + This method retrieves the authorization policy from the M365 Entra client, and then checks if the 'guest_user_role_id' matches the predefined restricted role ID. If it matches, the check passes; otherwise, it fails. Returns: - List[CheckReportMicrosoft365]: A list containing a single check report detailing + List[CheckReportM365]: A list containing a single check report detailing the status and details of the guest user access restriction. """ findings = [] auth_policy = entra_client.authorization_policy - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=auth_policy if auth_policy else {}, resource_name=auth_policy.name if auth_policy else "Authorization Policy", diff --git a/prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/__init__.py b/prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/__init__.py rename to prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.metadata.json b/prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.metadata.json rename to prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.metadata.json index 066cb1fa77..ac38009fff 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.metadata.json +++ b/prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_policy_restricts_user_consent_for_apps", "CheckTitle": "Ensure 'User consent for applications' is set to 'Do not allow user consent'", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.py b/prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.py similarity index 82% rename from prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.py rename to prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.py index a8ac22f008..1d54ab41df 100644 --- a/prowler/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.py +++ b/prowler/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/entra_policy_restricts_user_consent_for_apps.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client class entra_policy_restricts_user_consent_for_apps(Check): @@ -12,16 +12,16 @@ class entra_policy_restricts_user_consent_for_apps(Check): If such consent is disabled, the check passes. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check for user consent restrictions. Returns: - List[CheckReportMicrosoft365]: A list containing the result of the check. + List[CheckReportM365]: A list containing the result of the check. """ findings = [] auth_policy = entra_client.authorization_policy - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=auth_policy if auth_policy else {}, resource_name=auth_policy.name if auth_policy else "Authorization Policy", diff --git a/prowler/providers/microsoft365/services/entra/entra_service.py b/prowler/providers/m365/services/entra/entra_service.py similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_service.py rename to prowler/providers/m365/services/entra/entra_service.py index 16594a8941..d752562023 100644 --- a/prowler/providers/microsoft365/services/entra/entra_service.py +++ b/prowler/providers/m365/services/entra/entra_service.py @@ -7,12 +7,12 @@ from uuid import UUID from pydantic import BaseModel from prowler.lib.logger import logger -from prowler.providers.microsoft365.lib.service.service import Microsoft365Service -from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider +from prowler.providers.m365.lib.service.service import M365Service +from prowler.providers.m365.m365_provider import M365Provider -class Entra(Microsoft365Service): - def __init__(self, provider: Microsoft365Provider): +class Entra(M365Service): + def __init__(self, provider: M365Provider): super().__init__(provider) loop = get_event_loop() diff --git a/prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/__init__.py b/prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/__init__.py rename to prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.metadata.json b/prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.metadata.json rename to prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.metadata.json index 59676ee664..5cc28bd7ae 100644 --- a/prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.metadata.json +++ b/prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_thirdparty_integrated_apps_not_allowed", "CheckTitle": "Ensure third party integrated applications are not allowed", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.py b/prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.py similarity index 83% rename from prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.py rename to prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.py index 36ce95286c..5927990dbf 100644 --- a/prowler/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.py +++ b/prowler/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client class entra_thirdparty_integrated_apps_not_allowed(Check): @@ -14,20 +14,20 @@ class entra_thirdparty_integrated_apps_not_allowed(Check): metadata: Metadata associated with the check (inherited from Check). """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """Execute the check to ensure third-party integrated apps are not allowed for non-admin users. This method checks if the authorization policy allows non-admin users to create apps. If the policy allows app creation, the check fails. Otherwise, the check passes. Returns: - List[CheckReportMicrosoft365]: A list containing the result of the check for app creation policy. + List[CheckReportM365]: A list containing the result of the check for app creation policy. """ findings = [] auth_policy = entra_client.authorization_policy if auth_policy: - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=auth_policy if auth_policy else {}, resource_name=( diff --git a/prowler/providers/microsoft365/services/sharepoint/__init__.py b/prowler/providers/m365/services/entra/entra_users_mfa_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/sharepoint/__init__.py rename to prowler/providers/m365/services/entra/entra_users_mfa_enabled/__init__.py diff --git a/prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.metadata.json b/prowler/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.metadata.json rename to prowler/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.metadata.json index 75f82197c5..1d2e25f29d 100644 --- a/prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.metadata.json +++ b/prowler/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "entra_users_mfa_enabled", "CheckTitle": "Ensure multifactor authentication is enabled for all users.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.py b/prowler/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.py similarity index 83% rename from prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.py rename to prowler/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.py index 8159c3ebc4..a87d1edec3 100644 --- a/prowler/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.py +++ b/prowler/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled.py @@ -1,8 +1,8 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.entra.entra_client import entra_client -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.entra.entra_client import entra_client +from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessGrantControl, ConditionalAccessPolicyState, ) @@ -18,7 +18,7 @@ class entra_users_mfa_enabled(Check): The check fails if no enabled policy is found that requires MFA for all users. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the admin MFA requirement check for all users. @@ -26,11 +26,11 @@ class entra_users_mfa_enabled(Check): indicating whether MFA is enforced for users in all users. Returns: - List[CheckReportMicrosoft365]: A list containing a single report with the result of the check. + List[CheckReportM365]: A list containing a single report with the result of the check. """ findings = [] - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource={}, resource_name="Conditional Access Policies", @@ -59,7 +59,7 @@ class entra_users_mfa_enabled(Check): ConditionalAccessGrantControl.MFA in policy.grant_controls.built_in_controls ): - report = CheckReportMicrosoft365( + report = CheckReportM365( metadata=self.metadata(), resource=entra_client.conditional_access_policies, resource_name=policy.display_name, diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/__init__.py b/prowler/providers/m365/services/purview/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/__init__.py rename to prowler/providers/m365/services/purview/__init__.py diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/__init__.py b/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/__init__.py rename to prowler/providers/m365/services/purview/purview_audit_log_search_enabled/__init__.py diff --git a/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled.metadata.json b/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled.metadata.json new file mode 100644 index 0000000000..ef49cfa524 --- /dev/null +++ b/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "m365", + "CheckID": "purview_audit_log_search_enabled", + "CheckTitle": "Ensure Purview audit log search is enabled", + "CheckType": [], + "ServiceName": "purview", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "critical", + "ResourceType": "Purview Settings", + "Description": "Ensure Purview audit log search is enabled.", + "Risk": "Disabling Microsoft 365 audit log search can hinder the ability to track and monitor user and admin activities, making it harder to detect suspicious behavior, security incidents, or compliance violations. This can result in undetected breaches and inability to respond to incidents effectively.", + "RelatedUrl": "https://learn.microsoft.com/en-us/purview/audit-search?tabs=microsoft-purview-portal", + "Remediation": { + "Code": { + "CLI": "Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true", + "NativeIaC": "", + "Other": "1. Navigate to Microsoft Purview https://compliance.microsoft.com. 2. Select Audit to open the audit search. 3. Click Start recording user and admin activity next to the information warning at the top. 4. Click Yes on the dialog box to confirm.", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure that Microsoft 365 audit log search is enabled to maintain a comprehensive record of user and admin activities. This will help improve security monitoring, support compliance needs, and provide critical insights for responding to incidents.", + "Url": "https://learn.microsoft.com/en-us/purview/audit-search?tabs=microsoft-purview-portal" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled.py b/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled.py new file mode 100644 index 0000000000..f6884dbfcf --- /dev/null +++ b/prowler/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled.py @@ -0,0 +1,41 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.purview.purview_client import purview_client + + +class purview_audit_log_search_enabled(Check): + """Check if Purview audit log search is enabled. + + Attributes: + metadata: Metadata associated with the check (inherited from Check). + """ + + def execute(self) -> List[CheckReportM365]: + """Execute the check for audit log search + + This method checks if audit log search is enabled Purview settings + + Returns: + List[CheckReportM365]: A list of reports containing the result of the check. + """ + findings = [] + audit_log_config = purview_client.audit_log_config + report = CheckReportM365( + metadata=self.metadata(), + resource=audit_log_config if audit_log_config else {}, + resource_name="Purview Settings", + resource_id="purviewSettings", + ) + report.status = "FAIL" + report.status_extended = "Purview audit log search is not enabled." + + if purview_client.audit_log_config and getattr( + purview_client.audit_log_config, "audit_log_search", False + ): + report.status = "PASS" + report.status_extended = "Purview audit log search is enabled." + + findings.append(report) + + return findings diff --git a/prowler/providers/m365/services/purview/purview_client.py b/prowler/providers/m365/services/purview/purview_client.py new file mode 100644 index 0000000000..dea423b967 --- /dev/null +++ b/prowler/providers/m365/services/purview/purview_client.py @@ -0,0 +1,4 @@ +from prowler.providers.common.provider import Provider +from prowler.providers.m365.services.purview.purview_service import Purview + +purview_client = Purview(Provider.get_global_provider()) diff --git a/prowler/providers/m365/services/purview/purview_service.py b/prowler/providers/m365/services/purview/purview_service.py new file mode 100644 index 0000000000..5d6fdfce36 --- /dev/null +++ b/prowler/providers/m365/services/purview/purview_service.py @@ -0,0 +1,33 @@ +from pydantic import BaseModel + +from prowler.lib.logger import logger +from prowler.providers.m365.lib.service.service import M365Service +from prowler.providers.m365.m365_provider import M365Provider + + +class Purview(M365Service): + def __init__(self, provider: M365Provider): + super().__init__(provider) + self.powershell.connect_exchange_online() + self.audit_log_config = self._get_audit_log_config() + self.powershell.close() + + def _get_audit_log_config(self): + logger.info("M365 - Getting Admin Audit Log settings...") + audit_log_config = None + try: + audit_log_config_response = self.powershell.get_audit_log_config() + audit_log_config = AuditLogConfig( + audit_log_search=audit_log_config_response.get( + "UnifiedAuditLogIngestionEnabled", False + ) + ) + except Exception as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return audit_log_config + + +class AuditLogConfig(BaseModel): + audit_log_search: bool diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/__init__.py b/prowler/providers/m365/services/sharepoint/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/__init__.py rename to prowler/providers/m365/services/sharepoint/__init__.py diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_client.py b/prowler/providers/m365/services/sharepoint/sharepoint_client.py similarity index 53% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_client.py rename to prowler/providers/m365/services/sharepoint/sharepoint_client.py index fc547bc167..be3cf6377b 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_client.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_client.py @@ -1,6 +1,4 @@ from prowler.providers.common.provider import Provider -from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( - SharePoint, -) +from prowler.providers.m365.services.sharepoint.sharepoint_service import SharePoint sharepoint_client = SharePoint(Provider.get_global_provider()) diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/__init__.py b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/__init__.py similarity index 100% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/__init__.py rename to prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/__init__.py diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.metadata.json b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.metadata.json rename to prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.metadata.json index ee559a57a0..dbc758be2c 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.metadata.json +++ b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "sharepoint_external_sharing_managed", "CheckTitle": "Ensure SharePoint external sharing is managed through domain whitelists/blacklists.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py similarity index 88% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py rename to prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py index 9fd8c432a1..087d9a2540 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.sharepoint.sharepoint_client import ( sharepoint_client, ) @@ -19,7 +19,7 @@ class sharepoint_external_sharing_managed(Check): of verifying that the allowed/blocked domain list is not empty. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the SharePoint external sharing management check. @@ -27,12 +27,12 @@ class sharepoint_external_sharing_managed(Check): generates a report indicating whether external sharing is managed via domain restrictions. Returns: - List[CheckReportMicrosoft365]: A list containing a report with the result of the check. + List[CheckReportM365]: A list containing a report with the result of the check. """ findings = [] settings = sharepoint_client.settings if settings: - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/__init__.py b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.metadata.json b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.metadata.json rename to prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.metadata.json index 63b040672d..5b9426131d 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.metadata.json +++ b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "sharepoint_external_sharing_restricted", "CheckTitle": "Ensure external content sharing is restricted.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py similarity index 83% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py rename to prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py index 639ce00df3..728231a22f 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.sharepoint.sharepoint_client import ( sharepoint_client, ) @@ -15,7 +15,7 @@ class sharepoint_external_sharing_restricted(Check): setting is used, legacy sharing may be allowed, increasing the risk of unauthorized data access. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the SharePoint external sharing restriction check. @@ -23,12 +23,12 @@ class sharepoint_external_sharing_restricted(Check): indicating whether external sharing is restricted to 'New and existing guests' (ExternalUserSharingOnly). Returns: - List[Check_Report_Microsoft365]: A list containing a report with the result of the check. + List[Check_Report_M365]: A list containing a report with the result of the check. """ findings = [] settings = sharepoint_client.settings if settings: - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/__init__.py b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.metadata.json b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.metadata.json rename to prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.metadata.json index 89acd7e46a..9eba868289 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.metadata.json +++ b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "sharepoint_guest_sharing_restricted", "CheckTitle": "Ensure that SharePoint guest users cannot share items they don't own.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py similarity index 81% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py rename to prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py index 3666a837b1..ff66780a87 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.sharepoint.sharepoint_client import ( sharepoint_client, ) @@ -16,7 +16,7 @@ class sharepoint_guest_sharing_restricted(Check): to prevent external users from resharing is enabled. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the SharePoint guest sharing restriction check. @@ -24,12 +24,12 @@ class sharepoint_guest_sharing_restricted(Check): and generates a report indicating whether guest users are prevented from sharing items they do not own. Returns: - List[CheckReportMicrosoft365]: A list containing a report with the result of the check. + List[CheckReportM365]: A list containing a report with the result of the check. """ findings = [] settings = sharepoint_client.settings if settings: - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/__init__.py b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.metadata.json b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.metadata.json similarity index 98% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.metadata.json rename to prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.metadata.json index e9c0047115..ec7355bda0 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.metadata.json +++ b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "microsoft365", + "Provider": "m365", "CheckID": "sharepoint_modern_authentication_required", "CheckTitle": "Ensure modern authentication for SharePoint applications is required.", "CheckType": [], diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py similarity index 83% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py rename to prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py index 04f61084b2..6d5761ca35 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py @@ -1,7 +1,7 @@ from typing import List -from prowler.lib.check.models import Check, CheckReportMicrosoft365 -from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import ( +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.sharepoint.sharepoint_client import ( sharepoint_client, ) @@ -18,7 +18,7 @@ class sharepoint_modern_authentication_required(Check): The check fails if modern authentication is not enforced, indicating that legacy protocols may be used. """ - def execute(self) -> List[CheckReportMicrosoft365]: + def execute(self) -> List[CheckReportM365]: """ Execute the SharePoint modern authentication requirement check. @@ -26,12 +26,12 @@ class sharepoint_modern_authentication_required(Check): generates a report indicating whether modern authentication is required for SharePoint applications. Returns: - List[CheckReportMicrosoft365]: A list containing the report object with the result of the check. + List[CheckReportM365]: A list containing the report object with the result of the check. """ findings = [] settings = sharepoint_client.settings if settings: - report = CheckReportMicrosoft365( + report = CheckReportM365( self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", diff --git a/prowler/providers/microsoft365/services/sharepoint/sharepoint_service.py b/prowler/providers/m365/services/sharepoint/sharepoint_service.py similarity index 85% rename from prowler/providers/microsoft365/services/sharepoint/sharepoint_service.py rename to prowler/providers/m365/services/sharepoint/sharepoint_service.py index bb8f2c6903..6040a321b8 100644 --- a/prowler/providers/microsoft365/services/sharepoint/sharepoint_service.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_service.py @@ -5,12 +5,12 @@ from msgraph.generated.models.o_data_errors.o_data_error import ODataError from pydantic import BaseModel from prowler.lib.logger import logger -from prowler.providers.microsoft365.lib.service.service import Microsoft365Service -from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider +from prowler.providers.m365.lib.service.service import M365Service +from prowler.providers.m365.m365_provider import M365Provider -class SharePoint(Microsoft365Service): - def __init__(self, provider: Microsoft365Provider): +class SharePoint(M365Service): + def __init__(self, provider: M365Provider): super().__init__(provider) loop = get_event_loop() self.tenant_domain = provider.identity.tenant_domain @@ -22,7 +22,7 @@ class SharePoint(Microsoft365Service): self.settings = attributes[0] async def _get_settings(self): - logger.info("Microsoft365 - Getting SharePoint global settings...") + logger.info("M365 - Getting SharePoint global settings...") settings = None try: global_settings = await self.client.admin.sharepoint.settings.get() diff --git a/prowler/providers/m365/services/teams/__init__.py b/prowler/providers/m365/services/teams/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/m365/services/teams/teams_client.py b/prowler/providers/m365/services/teams/teams_client.py new file mode 100644 index 0000000000..9727500d7d --- /dev/null +++ b/prowler/providers/m365/services/teams/teams_client.py @@ -0,0 +1,4 @@ +from prowler.providers.common.provider import Provider +from prowler.providers.m365.services.teams.teams_service import Teams + +teams_client = Teams(Provider.get_global_provider()) diff --git a/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/__init__.py b/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted.metadata.json b/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted.metadata.json new file mode 100644 index 0000000000..f433685c62 --- /dev/null +++ b/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "m365", + "CheckID": "teams_external_file_sharing_restricted", + "CheckTitle": "Ensure external file sharing in Teams is enabled for only approved cloud storage services", + "CheckType": [], + "ServiceName": "teams", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "high", + "ResourceType": "Teams Settings", + "Description": "", + "Risk": "Allowing unrestricted third-party cloud storage services in Teams increases the risk of data exfiltration, compliance violations, and unauthorized access to sensitive information. Users may store or share data through unapproved platforms with weaker security controls.", + "RelatedUrl": "https://learn.microsoft.com/en-us/powershell/module/teams/get-csteamsclientconfiguration?view=teams-ps", + "Remediation": { + "Code": { + "CLI": "Set-CsTeamsClientConfiguration -AllowGoogleDrive $false -AllowShareFile $false -AllowBox $false -AllowDropBox $false -AllowEgnyte $false", + "NativeIaC": "", + "Other": "1. Navigate to Microsoft Teams admin center https://admin.teams.microsoft.com. 2. Click to expand Teams select Teams settings. 3. Set any unauthorized providers to Off.", + "Terraform": "" + }, + "Recommendation": { + "Text": "Restrict external file sharing in Teams to only approved cloud storage providers, such as SharePoint Online and OneDrive. Configure Teams policies to block unauthorized services and enforce compliance with organizational data protection standards.", + "Url": "https://learn.microsoft.com/en-us/powershell/module/teams/get-csteamsclientconfiguration?view=teams-ps" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted.py b/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted.py new file mode 100644 index 0000000000..2ec8cc87f8 --- /dev/null +++ b/prowler/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted.py @@ -0,0 +1,67 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportM365 +from prowler.providers.m365.services.teams.teams_client import teams_client +from prowler.providers.m365.services.teams.teams_service import CloudStorageSettings + + +class teams_external_file_sharing_restricted(Check): + """Check if external file sharing is restricted in Teams. + + Attributes: + metadata: Metadata associated with the check (inherited from Check). + """ + + def execute(self) -> List[CheckReportM365]: + """Execute the check for external file sharing settings in Teams. + + This method checks if external file sharing is restricted in Teams. If external file sharing + is restricted to only approved cloud storage services the check passes; otherwise, it fails. + + Returns: + List[CheckReportM365]: A list of reports containing the result of the check. + """ + findings = [] + cloud_storage_settings = teams_client.teams_settings.cloud_storage_settings + report = CheckReportM365( + metadata=self.metadata(), + resource=cloud_storage_settings if cloud_storage_settings else {}, + resource_name="Cloud Storage Settings", + resource_id="cloudStorageSettings", + ) + report.status = "FAIL" + report.status_extended = "External file sharing is not restricted to only approved cloud storage services." + + allowed_services = teams_client.audit_config.get( + "allowed_cloud_storage_services", [] + ) + if cloud_storage_settings: + # Get storage services from CloudStorageSettings class items + storage_services = [ + attr + for attr, type in CloudStorageSettings.__annotations__.items() + if type is bool + ] + + # Check if all services are disabled when no allowed services are specified + # or if all enabled services are in the allowed list + if ( + not allowed_services + and all( + not getattr(cloud_storage_settings, service, True) + for service in storage_services + ) + ) or ( + allowed_services + and not any( + getattr(cloud_storage_settings, service, True) + and service not in allowed_services + for service in storage_services + ) + ): + report.status = "PASS" + report.status_extended = "External file sharing is restricted to only approved cloud storage services." + + findings.append(report) + + return findings diff --git a/prowler/providers/m365/services/teams/teams_service.py b/prowler/providers/m365/services/teams/teams_service.py new file mode 100644 index 0000000000..1415b6118b --- /dev/null +++ b/prowler/providers/m365/services/teams/teams_service.py @@ -0,0 +1,45 @@ +from pydantic import BaseModel + +from prowler.lib.logger import logger +from prowler.providers.m365.lib.service.service import M365Service +from prowler.providers.m365.m365_provider import M365Provider + + +class Teams(M365Service): + def __init__(self, provider: M365Provider): + super().__init__(provider) + self.powershell.connect_microsoft_teams() + self.teams_settings = self._get_teams_client_configuration() + self.powershell.close() + + def _get_teams_client_configuration(self): + logger.info("M365 - Getting Teams settings...") + settings = self.powershell.get_teams_settings() + try: + teams_settings = TeamsSettings( + cloud_storage_settings=CloudStorageSettings( + allow_box=settings.get("AllowBox", True), + allow_drop_box=settings.get("AllowDropBox", True), + allow_egnyte=settings.get("AllowEgnyte", True), + allow_google_drive=settings.get("AllowGoogleDrive", True), + allow_share_file=settings.get("AllowShareFile", True), + ) + ) + + except Exception as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return teams_settings + + +class CloudStorageSettings(BaseModel): + allow_box: bool + allow_drop_box: bool + allow_egnyte: bool + allow_google_drive: bool + allow_share_file: bool + + +class TeamsSettings(BaseModel): + cloud_storage_settings: CloudStorageSettings diff --git a/prowler/providers/microsoft365/lib/arguments/arguments.py b/prowler/providers/microsoft365/lib/arguments/arguments.py deleted file mode 100644 index d3e38642e7..0000000000 --- a/prowler/providers/microsoft365/lib/arguments/arguments.py +++ /dev/null @@ -1,48 +0,0 @@ -def init_parser(self): - """Init the Microsoft365 Provider CLI parser""" - microsoft365_parser = self.subparsers.add_parser( - "microsoft365", - parents=[self.common_providers_parser], - help="Microsoft365 Provider", - ) - # Authentication Modes - microsoft365_auth_subparser = microsoft365_parser.add_argument_group( - "Authentication Modes" - ) - microsoft365_auth_modes_group = ( - microsoft365_auth_subparser.add_mutually_exclusive_group() - ) - microsoft365_auth_modes_group.add_argument( - "--az-cli-auth", - action="store_true", - help="Use Azure CLI authentication to log in against Microsoft365", - ) - microsoft365_auth_modes_group.add_argument( - "--sp-env-auth", - action="store_true", - help="Use Azure Service Principal environment variables authentication to log in against Microsoft365", - ) - microsoft365_auth_modes_group.add_argument( - "--browser-auth", - action="store_true", - help="Use Azure interactive browser authentication to log in against Microsoft365", - ) - microsoft365_parser.add_argument( - "--tenant-id", - nargs="?", - default=None, - help="Microsoft365 Tenant ID to be used with --browser-auth option", - ) - # Regions - microsoft365_regions_subparser = microsoft365_parser.add_argument_group("Regions") - microsoft365_regions_subparser.add_argument( - "--region", - nargs="?", - default="Microsoft365Global", - choices=[ - "Microsoft365Global", - "Microsoft365GlobalChina", - "Microsoft365USGovernment", - ], - help="Microsoft365 region to be used, default is Microsoft365Global", - ) diff --git a/prowler/providers/microsoft365/lib/service/service.py b/prowler/providers/microsoft365/lib/service/service.py deleted file mode 100644 index 85f54b260e..0000000000 --- a/prowler/providers/microsoft365/lib/service/service.py +++ /dev/null @@ -1,14 +0,0 @@ -from msgraph import GraphServiceClient - -from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider - - -class Microsoft365Service: - def __init__( - self, - provider: Microsoft365Provider, - ): - self.client = GraphServiceClient(credentials=provider.session) - - self.audit_config = provider.audit_config - self.fixer_config = provider.fixer_config diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index 2dc9bef561..e9a4e6fad2 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -431,8 +431,8 @@ kubernetes: "TLS_RSA_WITH_AES_128_GCM_SHA256", ] -# Microsoft365 Configuration -microsoft365: +# M365 Configuration +m365: # Conditional Access Policy # policy.session_controls.sign_in_frequency.frequency in hours sign_in_frequency: 4 diff --git a/tests/lib/cli/parser_test.py b/tests/lib/cli/parser_test.py index 37bec15d94..a8f256ef36 100644 --- a/tests/lib/cli/parser_test.py +++ b/tests/lib/cli/parser_test.py @@ -1,3 +1,4 @@ +import sys import uuid from argparse import ArgumentTypeError @@ -16,11 +17,13 @@ prowler_command = "prowler" # capsys # https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html -prowler_default_usage_error = "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes,microsoft365,nhn,dashboard} ..." +prowler_default_usage_error = ( + "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,nhn,dashboard} ..." +) def mock_get_available_providers(): - return ["aws", "azure", "gcp", "kubernetes", "microsoft365", "nhn"] + return ["aws", "azure", "gcp", "kubernetes", "m365", "nhn"] @pytest.mark.arg_parser @@ -1363,3 +1366,13 @@ class Test_Parser: valid_role_names = ["prowler-role" "test@" "test=test+test,."] for role_name in valid_role_names: assert validate_role_session_name(role_name) == role_name + + def test_microsoft365_alias_conversion(self): + original_argv = sys.argv.copy() + try: + sys.argv = ["prowler", "microsoft365"] + parser = ProwlerArgumentParser() + args = parser.parse() + assert args.provider == "m365" + finally: + sys.argv = original_argv diff --git a/tests/lib/outputs/finding_test.py b/tests/lib/outputs/finding_test.py index 05270785cd..3dea2f614b 100644 --- a/tests/lib/outputs/finding_test.py +++ b/tests/lib/outputs/finding_test.py @@ -956,9 +956,9 @@ class TestFinding: "prowler.lib.outputs.finding.get_check_compliance", new=mock_get_check_compliance, ) - def test_transform_api_finding_microsoft365(self): + def test_transform_api_finding_m365(self): provider = MagicMock() - provider.type = "microsoft365" + provider.type = "m365" provider.identity.identity_type = "ms_identity_type" provider.identity.identity_id = "ms_identity_id" provider.identity.tenant_id = "ms-tenant-id" @@ -970,7 +970,7 @@ class TestFinding: dummy_finding.status = "PASS" dummy_finding.status_extended = "M365 check extended" check_metadata = { - "provider": "microsoft365", + "provider": "m365", "checkid": "m365-check-001", "checktitle": "Test M365 Check", "checktype": [], diff --git a/tests/lib/powershell/powershell_test.py b/tests/lib/powershell/powershell_test.py new file mode 100644 index 0000000000..6dab9349a0 --- /dev/null +++ b/tests/lib/powershell/powershell_test.py @@ -0,0 +1,125 @@ +from unittest.mock import MagicMock, patch + +from prowler.providers.m365.lib.powershell.m365_powershell import PowerShellSession + + +class TestPowerShellSession: + @patch("subprocess.Popen") + def test_init(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + session = PowerShellSession() + + mock_popen.assert_called_once() + assert session.process == mock_process + assert session.END == "" + session.close() + + @patch("subprocess.Popen") + def test_sanitize(self, _): + session = PowerShellSession() + + test_cases = [ + ("test@example.com", "test@example.com"), + ("test@example.com!", "test@example.com"), + ("test@example.com#", "test@example.com"), + ("test@example.com$", "test@example.com"), + ("test@example.com%", "test@example.com"), + ("test@example.com^", "test@example.com"), + ("test@example.com&", "test@example.com"), + ("test@example.com*", "test@example.com"), + ("test@example.com(", "test@example.com"), + ("test@example.com)", "test@example.com"), + ("test@example.com-", "test@example.com-"), + ("test@example.com_", "test@example.com_"), + ("test@example.com+", "test@example.com+"), + ("test_;echo pwned;password", "test_echopwnedpassword"), + ] + + for input_str, expected in test_cases: + assert session.sanitize(input_str) == expected + session.close() + + @patch("subprocess.Popen") + def test_remove_ansi(self, mock_popen): + session = PowerShellSession() + + test_cases = [ + ("\x1b[32mSuccess\x1b[0m", "Success"), + ("\x1b[31mError\x1b[0m", "Error"), + ("\x1b[33mWarning\x1b[0m", "Warning"), + ("Normal text", "Normal text"), + ("\x1b[1mBold\x1b[0m", "Bold"), + ] + + for input_str, expected in test_cases: + assert session.remove_ansi(input_str) == expected + session.close() + + @patch("subprocess.Popen") + def test_execute(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + session = PowerShellSession() + command = "Get-Command" + expected_output = '{"Name": "Get-Command"}' + + with patch.object(session, "read_output", return_value=expected_output): + result = session.execute(command) + + mock_process.stdin.write.assert_any_call(f"{command}\n") + mock_process.stdin.write.assert_any_call(f"Write-Output '{session.END}'\n") + assert result == {"Name": "Get-Command"} + session.close() + + @patch("subprocess.Popen") + def test_read_output(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + session = PowerShellSession() + + # Test normal output + with patch.object(session, "read_output", return_value="test@example.com"): + assert session.read_output() == "test@example.com" + + # Test timeout + mock_process.stdout.readline.return_value = "test output\n" + with patch.object(session, "remove_ansi", return_value="test output"): + assert session.read_output(timeout=0.1, default="") == "" + session.close() + + @patch("subprocess.Popen") + def test_json_parse_output(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + session = PowerShellSession() + + test_cases = [ + ('{"key": "value"}', {"key": "value"}), + ('[{"key": "value"}]', [{"key": "value"}]), + ( + '[{"key": "value"},{"key": "value"}]', + [{"key": "value"}, {"key": "value"}], + ), + ("[{}]", [{}]), + ("[{},{}]", [{}, {}]), + ("not json", {}), + ("", {}), + ] + + for input_str, expected in test_cases: + result = session.json_parse_output(input_str) + assert result == expected + session.close() + + @patch("subprocess.Popen") + def test_close(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + session = PowerShellSession() + + session.close() + + mock_process.stdin.flush.assert_called_once() + mock_process.terminate.assert_called_once() + mock_process = None diff --git a/tests/providers/microsoft365/lib/mutelist/fixtures/microsoft365_mutelist.yaml b/tests/providers/m365/lib/mutelist/fixtures/m365_mutelist.yaml similarity index 100% rename from tests/providers/microsoft365/lib/mutelist/fixtures/microsoft365_mutelist.yaml rename to tests/providers/m365/lib/mutelist/fixtures/m365_mutelist.yaml diff --git a/tests/providers/microsoft365/lib/mutelist/microsoft365_mutelist_test.py b/tests/providers/m365/lib/mutelist/m365_mutelist_test.py similarity index 82% rename from tests/providers/microsoft365/lib/mutelist/microsoft365_mutelist_test.py rename to tests/providers/m365/lib/mutelist/m365_mutelist_test.py index 5bbde2e89d..8df9a97292 100644 --- a/tests/providers/microsoft365/lib/mutelist/microsoft365_mutelist_test.py +++ b/tests/providers/m365/lib/mutelist/m365_mutelist_test.py @@ -1,17 +1,15 @@ import yaml from mock import MagicMock -from prowler.providers.microsoft365.lib.mutelist.mutelist import Microsoft365Mutelist +from prowler.providers.m365.lib.mutelist.mutelist import M365Mutelist from tests.lib.outputs.fixtures.fixtures import generate_finding_output -MUTELIST_FIXTURE_PATH = ( - "tests/providers/microsoft365/lib/mutelist/fixtures/microsoft365_mutelist.yaml" -) +MUTELIST_FIXTURE_PATH = "tests/providers/m365/lib/mutelist/fixtures/m365_mutelist.yaml" -class TestMicrosoft365Mutelist: +class TestM365Mutelist: def test_get_mutelist_file_from_local_file(self): - mutelist = Microsoft365Mutelist(mutelist_path=MUTELIST_FIXTURE_PATH) + mutelist = M365Mutelist(mutelist_path=MUTELIST_FIXTURE_PATH) with open(MUTELIST_FIXTURE_PATH) as f: mutelist_fixture = yaml.safe_load(f)["Mutelist"] @@ -21,7 +19,7 @@ class TestMicrosoft365Mutelist: def test_get_mutelist_file_from_local_file_non_existent(self): mutelist_path = "tests/lib/mutelist/fixtures/not_present" - mutelist = Microsoft365Mutelist(mutelist_path=mutelist_path) + mutelist = M365Mutelist(mutelist_path=mutelist_path) assert mutelist.mutelist == {} assert mutelist.mutelist_file_path == mutelist_path @@ -34,7 +32,7 @@ class TestMicrosoft365Mutelist: mutelist_fixture["Accounts1"] = mutelist_fixture["Accounts"] del mutelist_fixture["Accounts"] - mutelist = Microsoft365Mutelist(mutelist_content=mutelist_fixture) + mutelist = M365Mutelist(mutelist_content=mutelist_fixture) assert not mutelist.validate_mutelist() assert mutelist.mutelist == {} @@ -55,7 +53,7 @@ class TestMicrosoft365Mutelist: } } - mutelist = Microsoft365Mutelist(mutelist_content=mutelist_content) + mutelist = M365Mutelist(mutelist_content=mutelist_content) finding = MagicMock finding.tenant_id = "subscription_1" @@ -84,7 +82,7 @@ class TestMicrosoft365Mutelist: } } - mutelist = Microsoft365Mutelist(mutelist_content=mutelist_content) + mutelist = M365Mutelist(mutelist_content=mutelist_content) finding_1 = generate_finding_output( check_id="check_test", diff --git a/tests/providers/m365/lib/powershell/m365_powershell_test.py b/tests/providers/m365/lib/powershell/m365_powershell_test.py new file mode 100644 index 0000000000..f32cc1c780 --- /dev/null +++ b/tests/providers/m365/lib/powershell/m365_powershell_test.py @@ -0,0 +1,210 @@ +from unittest.mock import MagicMock, patch + +from prowler.providers.m365.lib.powershell.m365_powershell import M365PowerShell +from prowler.providers.m365.models import M365Credentials + + +class Testm365PowerShell: + @patch("subprocess.Popen") + def test_init(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + credentials = M365Credentials(user="test@example.com", passwd="test_password") + + with patch.object(M365PowerShell, "init_credential") as mock_init_credential: + session = M365PowerShell(credentials) + + mock_popen.assert_called_once() + mock_init_credential.assert_called_once_with(credentials) + assert session.process == mock_process + assert session.END == "" + session.close() + + @patch("subprocess.Popen") + def test_sanitize(self, _): + credentials = M365Credentials(user="test@example.com", passwd="test_password") + session = M365PowerShell(credentials) + + test_cases = [ + ("test@example.com", "test@example.com"), + ("test@example.com!", "test@example.com"), + ("test@example.com#", "test@example.com"), + ("test@example.com$", "test@example.com"), + ("test@example.com%", "test@example.com"), + ("test@example.com^", "test@example.com"), + ("test@example.com&", "test@example.com"), + ("test@example.com*", "test@example.com"), + ("test@example.com(", "test@example.com"), + ("test@example.com)", "test@example.com"), + ("test@example.com-", "test@example.com-"), + ("test@example.com_", "test@example.com_"), + ("test@example.com+", "test@example.com+"), + ("test_;echo pwned;password", "test_echopwnedpassword"), + ] + + for input_str, expected in test_cases: + assert session.sanitize(input_str) == expected + session.close() + + @patch("subprocess.Popen") + def test_init_credential(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + credentials = M365Credentials( + user="test@example.com", + passwd="test_password", + client_id="test_client_id", + client_secret="test_client_secret", + tenant_id="test_tenant_id", + ) + session = M365PowerShell(credentials) + + session.execute = MagicMock() + + session.init_credential(credentials) + + session.execute.assert_any_call(f'$user = "{credentials.user}"') + session.execute.assert_any_call( + f'$secureString = "{credentials.passwd}" | ConvertTo-SecureString' + ) + session.execute.assert_any_call( + "$credential = New-Object System.Management.Automation.PSCredential ($user, $secureString)" + ) + session.close() + + @patch("subprocess.Popen") + @patch("msal.ConfidentialClientApplication") + def test_test_credentials(self, mock_msal, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_msal_instance = MagicMock() + mock_msal.return_value = mock_msal_instance + mock_msal_instance.acquire_token_by_username_password.return_value = { + "access_token": "test_token" + } + + credentials = M365Credentials( + user="test@example.com", + passwd="test_password", + client_id="test_client_id", + client_secret="test_client_secret", + tenant_id="test_tenant_id", + ) + session = M365PowerShell(credentials) + + session.execute = MagicMock() + session.process.stdin.write = MagicMock() + session.read_output = MagicMock(return_value="decrypted_password") + + assert session.test_credentials(credentials) is True + + session.execute.assert_any_call( + f'$securePassword = "{credentials.passwd}" | ConvertTo-SecureString\n' + ) + session.execute.assert_any_call( + f'$credential = New-Object System.Management.Automation.PSCredential("{credentials.user}", $securePassword)\n' + ) + session.process.stdin.write.assert_any_call( + 'Write-Output "$($credential.GetNetworkCredential().Password)"\n' + ) + session.process.stdin.write.assert_any_call(f"Write-Output '{session.END}'\n") + + mock_msal.assert_called_once_with( + client_id="test_client_id", + client_credential="test_client_secret", + authority="https://login.microsoftonline.com/test_tenant_id", + ) + mock_msal_instance.acquire_token_by_username_password.assert_called_once_with( + username="test@example.com", + password="decrypted_password", + scopes=["https://graph.microsoft.com/.default"], + ) + session.close() + + @patch("subprocess.Popen") + def test_remove_ansi(self, mock_popen): + credentials = M365Credentials(user="test@example.com", passwd="test_password") + session = M365PowerShell(credentials) + + test_cases = [ + ("\x1b[32mSuccess\x1b[0m", "Success"), + ("\x1b[31mError\x1b[0m", "Error"), + ("\x1b[33mWarning\x1b[0m", "Warning"), + ("Normal text", "Normal text"), + ("\x1b[1mBold\x1b[0m", "Bold"), + ] + + for input_str, expected in test_cases: + assert session.remove_ansi(input_str) == expected + session.close() + + @patch("subprocess.Popen") + def test_execute(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + credentials = M365Credentials(user="test@example.com", passwd="test_password") + session = M365PowerShell(credentials) + command = "Get-Command" + expected_output = '{"Name": "Get-Command"}' + + with patch.object(session, "read_output", return_value=expected_output): + result = session.execute(command) + + mock_process.stdin.write.assert_any_call(f"{command}\n") + mock_process.stdin.write.assert_any_call(f"Write-Output '{session.END}'\n") + assert result == {"Name": "Get-Command"} + session.close() + + @patch("subprocess.Popen") + def test_read_output(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + credentials = M365Credentials(user="test@example.com", passwd="test_password") + session = M365PowerShell(credentials) + + # Test normal output + with patch.object(session, "read_output", return_value="test@example.com"): + assert session.read_output() == "test@example.com" + + # Test timeout + mock_process.stdout.readline.return_value = "test output\n" + with patch.object(session, "remove_ansi", return_value="test output"): + assert session.read_output(timeout=0.1, default="") == "" + session.close() + + @patch("subprocess.Popen") + def test_json_parse_output(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + credentials = M365Credentials(user="test@example.com", passwd="test_password") + session = M365PowerShell(credentials) + + test_cases = [ + ('{"key": "value"}', {"key": "value"}), + ('[{"key": "value"}]', [{"key": "value"}]), + ( + '[{"key": "value"},{"key": "value"}]', + [{"key": "value"}, {"key": "value"}], + ), + ("[{}]", [{}]), + ("[{},{}]", [{}, {}]), + ("not json", {}), + ("", {}), + ] + + for input_str, expected in test_cases: + result = session.json_parse_output(input_str) + assert result == expected + session.close() + + @patch("subprocess.Popen") + def test_close(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + credentials = M365Credentials(user="test@example.com", passwd="test_password") + session = M365PowerShell(credentials) + + session.close() + + mock_process.stdin.flush.assert_called_once() + mock_process.terminate.assert_called_once() diff --git a/tests/providers/microsoft365/lib/regions/microsoft365_regions_test.py b/tests/providers/m365/lib/regions/m365_regions_test.py similarity index 76% rename from tests/providers/microsoft365/lib/regions/microsoft365_regions_test.py rename to tests/providers/m365/lib/regions/m365_regions_test.py index 49ec5a480d..676e769276 100644 --- a/tests/providers/microsoft365/lib/regions/microsoft365_regions_test.py +++ b/tests/providers/m365/lib/regions/m365_regions_test.py @@ -1,6 +1,6 @@ from azure.identity import AzureAuthorityHosts -from prowler.providers.microsoft365.lib.regions.regions import ( +from prowler.providers.m365.lib.regions.regions import ( MICROSOFT365_CHINA_CLOUD, MICROSOFT365_GENERIC_CLOUD, MICROSOFT365_US_GOV_CLOUD, @@ -8,25 +8,25 @@ from prowler.providers.microsoft365.lib.regions.regions import ( ) -class Test_microsoft365_regions: +class Test_m365_regions: def test_get_regions_config(self): allowed_regions = [ - "Microsoft365Global", - "Microsoft365China", - "Microsoft365USGovernment", + "M365Global", + "M365China", + "M365USGovernment", ] expected_output = { - "Microsoft365Global": { + "M365Global": { "authority": None, "base_url": MICROSOFT365_GENERIC_CLOUD, "credential_scopes": [MICROSOFT365_GENERIC_CLOUD + "/.default"], }, - "Microsoft365China": { + "M365China": { "authority": AzureAuthorityHosts.AZURE_CHINA, "base_url": MICROSOFT365_CHINA_CLOUD, "credential_scopes": [MICROSOFT365_CHINA_CLOUD + "/.default"], }, - "Microsoft365USGovernment": { + "M365USGovernment": { "authority": AzureAuthorityHosts.AZURE_GOVERNMENT, "base_url": MICROSOFT365_US_GOV_CLOUD, "credential_scopes": [MICROSOFT365_US_GOV_CLOUD + "/.default"], diff --git a/tests/providers/microsoft365/microsoft365_fixtures.py b/tests/providers/m365/m365_fixtures.py similarity index 53% rename from tests/providers/microsoft365/microsoft365_fixtures.py rename to tests/providers/m365/m365_fixtures.py index 1dbb09c612..0eb3c203e1 100644 --- a/tests/providers/microsoft365/microsoft365_fixtures.py +++ b/tests/providers/m365/m365_fixtures.py @@ -1,10 +1,11 @@ from azure.identity import DefaultAzureCredential from mock import MagicMock -from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider -from prowler.providers.microsoft365.models import ( - Microsoft365IdentityInfo, - Microsoft365RegionConfig, +from prowler.providers.m365.m365_provider import M365Provider +from prowler.providers.m365.models import ( + M365Credentials, + M365IdentityInfo, + M365RegionConfig, ) # Azure Identity @@ -18,20 +19,24 @@ LOCATION = "global" # Mocked Azure Audit Info -def set_mocked_microsoft365_provider( - credentials: DefaultAzureCredential = DefaultAzureCredential(), - identity: Microsoft365IdentityInfo = Microsoft365IdentityInfo( +def set_mocked_m365_provider( + session_credentials: DefaultAzureCredential = DefaultAzureCredential(), + credentials: M365Credentials = M365Credentials( + user="user@email.com", passwd="111111aa111111aaa1111" + ), + identity: M365IdentityInfo = M365IdentityInfo( identity_id=IDENTITY_ID, identity_type=IDENTITY_TYPE, tenant_id=TENANT_ID, tenant_domain=DOMAIN, ), audit_config: dict = None, - azure_region_config: Microsoft365RegionConfig = Microsoft365RegionConfig(), -) -> Microsoft365Provider: + azure_region_config: M365RegionConfig = M365RegionConfig(), +) -> M365Provider: provider = MagicMock() - provider.type = "microsoft365" - provider.session.credentials = credentials + provider.type = "m365" + provider.session.credentials = session_credentials + provider.credentials = credentials provider.identity = identity provider.audit_config = audit_config provider.region_config = azure_region_config diff --git a/tests/providers/m365/m365_provider_test.py b/tests/providers/m365/m365_provider_test.py new file mode 100644 index 0000000000..22f0bef4b0 --- /dev/null +++ b/tests/providers/m365/m365_provider_test.py @@ -0,0 +1,452 @@ +from unittest.mock import patch +from uuid import uuid4 + +import pytest +from azure.core.credentials import AccessToken +from azure.identity import ( + ClientSecretCredential, + DefaultAzureCredential, + InteractiveBrowserCredential, +) +from mock import MagicMock + +from prowler.config.config import ( + default_config_file_path, + default_fixer_config_file_path, + load_and_validate_config_file, +) +from prowler.providers.common.models import Connection +from prowler.providers.m365.exceptions.exceptions import ( + M365HTTPResponseError, + M365MissingEnvironmentUserCredentialsError, + M365NoAuthenticationMethodError, +) +from prowler.providers.m365.m365_provider import M365Provider +from prowler.providers.m365.models import ( + M365Credentials, + M365IdentityInfo, + M365RegionConfig, +) +from tests.providers.m365.m365_fixtures import ( + CLIENT_ID, + CLIENT_SECRET, + DOMAIN, + IDENTITY_ID, + IDENTITY_TYPE, + LOCATION, + TENANT_ID, +) + + +class TestM365Provider: + def test_m365_provider(self): + tenant_id = None + client_id = None + client_secret = None + + fixer_config = load_and_validate_config_file( + "m365", default_fixer_config_file_path + ) + azure_region = "M365Global" + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + return_value=ClientSecretCredential( + client_id=CLIENT_ID, + tenant_id=TENANT_ID, + client_secret=CLIENT_SECRET, + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type=IDENTITY_TYPE, + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ), + ), + ): + m365_provider = M365Provider( + sp_env_auth=True, + az_cli_auth=False, + browser_auth=False, + env_auth=False, + tenant_id=tenant_id, + client_id=client_id, + client_secret=client_secret, + region=azure_region, + config_path=default_config_file_path, + fixer_config=fixer_config, + ) + + assert m365_provider.region_config == M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + assert m365_provider.identity == M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type=IDENTITY_TYPE, + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ) + + def test_m365_provider_env_auth(self): + tenant_id = None + client_id = None + client_secret = None + + fixer_config = load_and_validate_config_file( + "m365", default_fixer_config_file_path + ) + azure_region = "M365Global" + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + return_value=ClientSecretCredential( + client_id=CLIENT_ID, + tenant_id=TENANT_ID, + client_secret=CLIENT_SECRET, + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type=IDENTITY_TYPE, + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_powershell", + return_value=M365Credentials( + user="test@test.com", + passwd="password", + ), + ), + ): + m365_provider = M365Provider( + sp_env_auth=False, + az_cli_auth=False, + browser_auth=False, + env_auth=True, + tenant_id=tenant_id, + client_id=client_id, + client_secret=client_secret, + region=azure_region, + config_path=default_config_file_path, + fixer_config=fixer_config, + ) + + assert m365_provider.region_config == M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + assert m365_provider.identity == M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type=IDENTITY_TYPE, + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ) + + def test_m365_provider_cli_auth(self): + """Test M365 Provider initialization with CLI authentication""" + azure_region = "M365Global" + fixer_config = load_and_validate_config_file( + "m365", default_fixer_config_file_path + ) + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + return_value=DefaultAzureCredential( + exclude_environment_credential=True, + exclude_cli_credential=False, + exclude_managed_identity_credential=True, + exclude_visual_studio_code_credential=True, + exclude_shared_token_cache_credential=True, + exclude_powershell_credential=True, + exclude_browser_credential=True, + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ), + ), + ): + m365_provider = M365Provider( + sp_env_auth=False, + az_cli_auth=True, + browser_auth=False, + env_auth=False, + region=azure_region, + config_path=default_config_file_path, + fixer_config=fixer_config, + ) + + assert m365_provider.region_config == M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + assert m365_provider.identity == M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ) + assert isinstance(m365_provider.session, DefaultAzureCredential) + + def test_m365_provider_browser_auth(self): + """Test M365 Provider initialization with Browser authentication""" + azure_region = "M365Global" + fixer_config = load_and_validate_config_file( + "m365", default_fixer_config_file_path + ) + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + return_value=InteractiveBrowserCredential( + tenant_id=TENANT_ID, + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ), + ), + ): + m365_provider = M365Provider( + sp_env_auth=False, + az_cli_auth=False, + browser_auth=True, + env_auth=False, + tenant_id=TENANT_ID, + region=azure_region, + config_path=default_config_file_path, + fixer_config=fixer_config, + ) + + assert m365_provider.region_config == M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + assert m365_provider.identity == M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + ) + assert isinstance(m365_provider.session, InteractiveBrowserCredential) + + def test_test_connection_browser_auth(self): + with ( + patch( + "prowler.providers.m365.m365_provider.DefaultAzureCredential" + ) as mock_default_credential, + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.GraphServiceClient" + ) as mock_graph_client, + ): + # Mock the return value of DefaultAzureCredential + mock_credentials = MagicMock() + mock_credentials.get_token.return_value = AccessToken( + token="fake_token", expires_on=9999999999 + ) + mock_default_credential.return_value = mock_credentials + + # Mock setup_session to return a mocked session object + mock_session = MagicMock() + mock_setup_session.return_value = mock_session + + # Mock GraphServiceClient to avoid real API calls + mock_client = MagicMock() + mock_graph_client.return_value = mock_client + + test_connection = M365Provider.test_connection( + browser_auth=True, + tenant_id=str(uuid4()), + region="M365Global", + raise_on_exception=False, + ) + + assert isinstance(test_connection, Connection) + assert test_connection.is_connected + assert test_connection.error is None + + def test_test_connection_tenant_id_client_id_client_secret(self): + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" + ) as mock_validate_static_credentials, + ): + # Mock setup_session to return a mocked session object + mock_session = MagicMock() + mock_setup_session.return_value = mock_session + + # Mock ValidateStaticCredentials to avoid real API calls + mock_validate_static_credentials.return_value = None + + test_connection = M365Provider.test_connection( + tenant_id=str(uuid4()), + region="M365Global", + raise_on_exception=False, + client_id=str(uuid4()), + client_secret=str(uuid4()), + ) + + assert isinstance(test_connection, Connection) + assert test_connection.is_connected + assert test_connection.error is None + + def test_test_connection_tenant_id_client_id_client_secret_user_encrypted_password( + self, + ): + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" + ) as mock_validate_static_credentials, + ): + # Mock setup_session to return a mocked session object + mock_session = MagicMock() + mock_setup_session.return_value = mock_session + + # Mock ValidateStaticCredentials to avoid real API calls + mock_validate_static_credentials.return_value = None + + test_connection = M365Provider.test_connection( + tenant_id=str(uuid4()), + region="M365Global", + raise_on_exception=False, + client_id=str(uuid4()), + client_secret=str(uuid4()), + user="user@user.com", + encrypted_password="AAAA1111", + ) + + assert isinstance(test_connection, Connection) + assert test_connection.is_connected + assert test_connection.error is None + + def test_test_connection_with_httpresponseerror(self): + with patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session: + mock_setup_session.side_effect = M365HTTPResponseError( + file="test_file", original_exception="Simulated HttpResponseError" + ) + + with pytest.raises(M365HTTPResponseError) as exception: + M365Provider.test_connection( + az_cli_auth=True, + raise_on_exception=True, + ) + + assert exception.type == M365HTTPResponseError + assert ( + exception.value.args[0] + == "[6003] Error in HTTP response from Microsoft 365 - Simulated HttpResponseError" + ) + + def test_test_connection_with_exception(self): + with patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session: + mock_setup_session.side_effect = Exception("Simulated Exception") + + with pytest.raises(Exception) as exception: + M365Provider.test_connection( + sp_env_auth=True, + raise_on_exception=True, + ) + + assert exception.type is Exception + assert exception.value.args[0] == "Simulated Exception" + + def test_test_connection_without_any_method(self): + with pytest.raises(M365NoAuthenticationMethodError) as exception: + M365Provider.test_connection() + + assert exception.type == M365NoAuthenticationMethodError + assert ( + "M365 provider requires at least one authentication method set: [--env-auth | --az-cli-auth | --sp-env-auth | --browser-auth]" + in exception.value.args[0] + ) + + def test_setup_powershell_valid_credentials(self): + credentials_dict = { + "user": "test@example.com", + "encrypted_password": "test_password", + "client_id": "test_client_id", + "tenant_id": "test_tenant_id", + "client_secret": "test_client_secret", + } + + with patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.test_credentials", + return_value=True, + ): + result = M365Provider.setup_powershell( + env_auth=False, m365_credentials=credentials_dict + ) + + assert result.user == credentials_dict["user"] + assert result.passwd == credentials_dict["encrypted_password"] + + def test_setup_powershell_invalid_env_credentials(self): + credentials = None + + with patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell" + ) as mock_powershell: + mock_session = MagicMock() + mock_session.test_credentials.return_value = False + mock_powershell.return_value = mock_session + + with pytest.raises(M365MissingEnvironmentUserCredentialsError) as exc_info: + M365Provider.setup_powershell( + env_auth=True, m365_credentials=credentials + ) + + assert ( + "Missing M365_USER or M365_ENCRYPTED_PASSWORD environment variables required for credentials authentication" + in str(exc_info.value) + ) + mock_session.test_credentials.assert_not_called() diff --git a/tests/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility_test.py b/tests/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility_test.py similarity index 68% rename from tests/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility_test.py rename to tests/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility_test.py index 4f7c5c2bc0..9e8ccfbc7d 100644 --- a/tests/providers/microsoft365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility_test.py +++ b/tests/providers/m365/services/admincenter/admincenter_groups_not_public_visibility/admincenter_groups_not_public_visibility_test.py @@ -1,10 +1,7 @@ from unittest import mock from uuid import uuid4 -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_admincenter_groups_not_public_visibility: @@ -16,14 +13,14 @@ class Test_admincenter_groups_not_public_visibility: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import ( + from prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import ( admincenter_groups_not_public_visibility, ) @@ -41,17 +38,17 @@ class Test_admincenter_groups_not_public_visibility: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import ( + from prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import ( admincenter_groups_not_public_visibility, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( Group, ) @@ -79,17 +76,17 @@ class Test_admincenter_groups_not_public_visibility: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import ( + from prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import ( admincenter_groups_not_public_visibility, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( Group, ) diff --git a/tests/providers/microsoft365/services/admincenter/admincenter_service_test.py b/tests/providers/m365/services/admincenter/admincenter_service_test.py similarity index 65% rename from tests/providers/microsoft365/services/admincenter/admincenter_service_test.py rename to tests/providers/m365/services/admincenter/admincenter_service_test.py index 1aaf11f8f4..f72c14ce71 100644 --- a/tests/providers/microsoft365/services/admincenter/admincenter_service_test.py +++ b/tests/providers/m365/services/admincenter/admincenter_service_test.py @@ -1,16 +1,13 @@ from unittest.mock import patch -from prowler.providers.microsoft365.models import Microsoft365IdentityInfo -from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( +from prowler.providers.m365.models import M365IdentityInfo +from prowler.providers.m365.services.admincenter.admincenter_service import ( AdminCenter, DirectoryRole, Group, User, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider async def mock_admincenter_get_users(_): @@ -40,41 +37,39 @@ async def mock_admincenter_get_groups(_): @patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_service.AdminCenter._get_users", + "prowler.providers.m365.services.admincenter.admincenter_service.AdminCenter._get_users", new=mock_admincenter_get_users, ) @patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_service.AdminCenter._get_directory_roles", + "prowler.providers.m365.services.admincenter.admincenter_service.AdminCenter._get_directory_roles", new=mock_admincenter_get_directory_roles, ) @patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_service.AdminCenter._get_groups", + "prowler.providers.m365.services.admincenter.admincenter_service.AdminCenter._get_groups", new=mock_admincenter_get_groups, ) class Test_AdminCenter_Service: def test_get_client(self): admincenter_client = AdminCenter( - set_mocked_microsoft365_provider( - identity=Microsoft365IdentityInfo(tenant_domain=DOMAIN) - ) + set_mocked_m365_provider(identity=M365IdentityInfo(tenant_domain=DOMAIN)) ) assert admincenter_client.client.__class__.__name__ == "GraphServiceClient" def test_get_users(self): - admincenter_client = AdminCenter(set_mocked_microsoft365_provider()) + admincenter_client = AdminCenter(set_mocked_m365_provider()) assert len(admincenter_client.users) == 1 assert admincenter_client.users["user-1@tenant1.es"].id == "id-1" assert admincenter_client.users["user-1@tenant1.es"].name == "User 1" def test_get_group_settings(self): - admincenter_client = AdminCenter(set_mocked_microsoft365_provider()) + admincenter_client = AdminCenter(set_mocked_m365_provider()) assert len(admincenter_client.groups) == 1 assert admincenter_client.groups["id-1"].id == "id-1" assert admincenter_client.groups["id-1"].name == "Test" assert admincenter_client.groups["id-1"].visibility == "Public" def test_get_directory_roles(self): - admincenter_client = AdminCenter(set_mocked_microsoft365_provider()) + admincenter_client = AdminCenter(set_mocked_m365_provider()) assert ( admincenter_client.directory_roles["GlobalAdministrator"].id == "id-directory-role" diff --git a/tests/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py b/tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py similarity index 69% rename from tests/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py rename to tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py index 15630b90c6..7c7cb7506b 100644 --- a/tests/providers/microsoft365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py +++ b/tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py @@ -1,10 +1,7 @@ from unittest import mock from uuid import uuid4 -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_admincenter_settings_password_never_expire: @@ -16,14 +13,14 @@ class Test_admincenter_settings_password_never_expire: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( + from prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( admincenter_settings_password_never_expire, ) @@ -41,17 +38,17 @@ class Test_admincenter_settings_password_never_expire: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( Domain, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( + from prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( admincenter_settings_password_never_expire, ) @@ -82,17 +79,17 @@ class Test_admincenter_settings_password_never_expire: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( Domain, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( + from prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( admincenter_settings_password_never_expire, ) diff --git a/tests/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint_test.py b/tests/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint_test.py similarity index 70% rename from tests/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint_test.py rename to tests/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint_test.py index f684c11988..06f807c1c2 100644 --- a/tests/providers/microsoft365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint_test.py +++ b/tests/providers/m365/services/admincenter/admincenter_users_admins_reduced_license_footprint/admincenter_users_admins_reduced_license_footprint_test.py @@ -1,10 +1,7 @@ from unittest import mock from uuid import uuid4 -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_admincenter_users_admins_reduced_license_footprint: @@ -16,14 +13,14 @@ class Test_admincenter_users_admins_reduced_license_footprint: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( + from prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( admincenter_users_admins_reduced_license_footprint, ) @@ -41,17 +38,17 @@ class Test_admincenter_users_admins_reduced_license_footprint: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( + from prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( admincenter_users_admins_reduced_license_footprint, ) @@ -78,17 +75,17 @@ class Test_admincenter_users_admins_reduced_license_footprint: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( + from prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( admincenter_users_admins_reduced_license_footprint, ) @@ -124,17 +121,17 @@ class Test_admincenter_users_admins_reduced_license_footprint: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( + from prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( admincenter_users_admins_reduced_license_footprint, ) @@ -170,17 +167,17 @@ class Test_admincenter_users_admins_reduced_license_footprint: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( + from prowler.providers.m365.services.admincenter.admincenter_users_admins_reduced_license_footprint.admincenter_users_admins_reduced_license_footprint import ( admincenter_users_admins_reduced_license_footprint, ) diff --git a/tests/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins_test.py b/tests/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins_test.py similarity index 74% rename from tests/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins_test.py rename to tests/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins_test.py index b7fafb56a9..994dbbcf49 100644 --- a/tests/providers/microsoft365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins_test.py +++ b/tests/providers/m365/services/admincenter/admincenter_users_between_two_and_four_global_admins/admincenter_users_between_two_and_four_global_admins_test.py @@ -1,10 +1,7 @@ from unittest import mock from uuid import uuid4 -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_admincenter_users_between_two_and_four_global_admins: @@ -16,14 +13,14 @@ class Test_admincenter_users_between_two_and_four_global_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( + from prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( admincenter_users_between_two_and_four_global_admins, ) @@ -41,18 +38,18 @@ class Test_admincenter_users_between_two_and_four_global_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( DirectoryRole, User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( + from prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( admincenter_users_between_two_and_four_global_admins, ) @@ -92,18 +89,18 @@ class Test_admincenter_users_between_two_and_four_global_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( DirectoryRole, User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( + from prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( admincenter_users_between_two_and_four_global_admins, ) @@ -154,18 +151,18 @@ class Test_admincenter_users_between_two_and_four_global_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", + "prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins.admincenter_client", new=admincenter_client, ), ): - from prowler.providers.microsoft365.services.admincenter.admincenter_service import ( + from prowler.providers.m365.services.admincenter.admincenter_service import ( DirectoryRole, User, ) - from prowler.providers.microsoft365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( + from prowler.providers.m365.services.admincenter.admincenter_users_between_two_and_four_global_admins.admincenter_users_between_two_and_four_global_admins import ( admincenter_users_between_two_and_four_global_admins, ) diff --git a/tests/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled_test.py b/tests/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled_test.py similarity index 76% rename from tests/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled_test.py rename to tests/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled_test.py index 9a72389813..8599a5d56a 100644 --- a/tests/providers/microsoft365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_admin_consent_workflow_enabled/entra_admin_consent_workflow_enabled_test.py @@ -1,12 +1,7 @@ from unittest import mock -from prowler.providers.microsoft365.services.entra.entra_service import ( - AdminConsentPolicy, -) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from prowler.providers.m365.services.entra.entra_service import AdminConsentPolicy +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_admin_consent_workflow_enabled: @@ -20,14 +15,14 @@ class Test_entra_admin_consent_workflow_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( entra_admin_consent_workflow_enabled, ) @@ -62,14 +57,14 @@ class Test_entra_admin_consent_workflow_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( entra_admin_consent_workflow_enabled, ) @@ -104,14 +99,14 @@ class Test_entra_admin_consent_workflow_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( entra_admin_consent_workflow_enabled, ) @@ -148,14 +143,14 @@ class Test_entra_admin_consent_workflow_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_consent_workflow_enabled.entra_admin_consent_workflow_enabled import ( entra_admin_consent_workflow_enabled, ) diff --git a/tests/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction_test.py b/tests/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction_test.py similarity index 84% rename from tests/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction_test.py rename to tests/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction_test.py index 23bed663b9..1226f07261 100644 --- a/tests/providers/microsoft365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction_test.py +++ b/tests/providers/m365/services/entra/entra_admin_portals_access_restriction/entra_admin_portals_access_restriction_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -14,10 +14,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_admin_portals_access_restriction: @@ -28,14 +25,14 @@ class Test_entra_admin_portals_access_restriction: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", + "prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( + from prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( entra_admin_portals_access_restriction, ) @@ -63,17 +60,17 @@ class Test_entra_admin_portals_access_restriction: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", + "prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( + from prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( entra_admin_portals_access_restriction, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -137,17 +134,17 @@ class Test_entra_admin_portals_access_restriction: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", + "prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( + from prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( entra_admin_portals_access_restriction, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -215,17 +212,17 @@ class Test_entra_admin_portals_access_restriction: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", + "prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( + from prowler.providers.m365.services.entra.entra_admin_portals_access_restriction.entra_admin_portals_access_restriction import ( entra_admin_portals_access_restriction, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only_test.py b/tests/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only_test.py similarity index 82% rename from tests/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only_test.py rename to tests/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only_test.py index 4e718d29f7..3eae3c9517 100644 --- a/tests/providers/microsoft365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only_test.py +++ b/tests/providers/m365/services/entra/entra_admin_users_cloud_only/entra_admin_users_cloud_only_test.py @@ -1,9 +1,7 @@ from unittest import mock -from prowler.providers.microsoft365.services.entra.entra_service import AdminRoles, User -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from prowler.providers.m365.services.entra.entra_service import AdminRoles, User +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_admin_users_cloud_only: @@ -17,14 +15,14 @@ class Test_entra_admin_users_cloud_only: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( + from prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( entra_admin_users_cloud_only, ) @@ -72,14 +70,14 @@ class Test_entra_admin_users_cloud_only: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( + from prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( entra_admin_users_cloud_only, ) @@ -127,14 +125,14 @@ class Test_entra_admin_users_cloud_only: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( + from prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( entra_admin_users_cloud_only, ) @@ -182,14 +180,14 @@ class Test_entra_admin_users_cloud_only: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( + from prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( entra_admin_users_cloud_only, ) @@ -237,14 +235,14 @@ class Test_entra_admin_users_cloud_only: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( + from prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( entra_admin_users_cloud_only, ) @@ -293,14 +291,14 @@ class Test_entra_admin_users_cloud_only: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( + from prowler.providers.m365.services.entra.entra_admin_users_cloud_only.entra_admin_users_cloud_only import ( entra_admin_users_cloud_only, ) diff --git a/tests/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled_test.py b/tests/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled_test.py similarity index 90% rename from tests/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled_test.py rename to tests/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled_test.py index 1a628de808..b25d48dd2c 100644 --- a/tests/providers/microsoft365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_admin_users_mfa_enabled/entra_admin_users_mfa_enabled_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicy, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_admin_users_mfa_enabled: @@ -31,14 +28,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -67,14 +64,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -143,14 +140,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -219,14 +216,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -300,14 +297,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -379,14 +376,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -474,14 +471,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) @@ -569,14 +566,14 @@ class Test_entra_admin_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_mfa_enabled.entra_admin_users_mfa_enabled import ( entra_admin_users_mfa_enabled, ) diff --git a/tests/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled_test.py b/tests/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled_test.py similarity index 87% rename from tests/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled_test.py rename to tests/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled_test.py index 7d6c5987b1..aa9ec89bca 100644 --- a/tests/providers/microsoft365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_admin_users_phishing_resistant_mfa_enabled/entra_admin_users_phishing_resistant_mfa_enabled_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, AuthenticationStrength, ConditionalAccessGrantControl, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_admin_users_phishing_resistant_mfa_enabled: @@ -29,14 +26,14 @@ class Test_entra_admin_users_phishing_resistant_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( entra_admin_users_phishing_resistant_mfa_enabled, ) @@ -65,17 +62,17 @@ class Test_entra_admin_users_phishing_resistant_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( entra_admin_users_phishing_resistant_mfa_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -157,17 +154,17 @@ class Test_entra_admin_users_phishing_resistant_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( entra_admin_users_phishing_resistant_mfa_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -252,17 +249,17 @@ class Test_entra_admin_users_phishing_resistant_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_phishing_resistant_mfa_enabled.entra_admin_users_phishing_resistant_mfa_enabled import ( entra_admin_users_phishing_resistant_mfa_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled_test.py b/tests/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled_test.py similarity index 88% rename from tests/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled_test.py rename to tests/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled_test.py index 9c2cfa7aa1..ecfbf2b771 100644 --- a/tests/providers/microsoft365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_admin_users_sign_in_frequency_enabled/entra_admin_users_sign_in_frequency_enabled_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessPolicyState, Conditions, @@ -14,10 +14,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyType, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_admin_users_sign_in_frequency_enabled: @@ -28,14 +25,14 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) @@ -65,17 +62,17 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -140,17 +137,17 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -236,17 +233,17 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -333,17 +330,17 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -428,17 +425,17 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -524,17 +521,17 @@ class Test_entra_admin_users_sign_in_frequency_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( + from prowler.providers.m365.services.entra.entra_admin_users_sign_in_frequency_enabled.entra_admin_users_sign_in_frequency_enabled import ( entra_admin_users_sign_in_frequency_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created_test.py b/tests/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created_test.py similarity index 72% rename from tests/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created_test.py rename to tests/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created_test.py index 4069310f4a..6aa9de8004 100644 --- a/tests/providers/microsoft365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created_test.py +++ b/tests/providers/m365/services/entra/entra_dynamic_group_for_guests_created/entra_dynamic_group_for_guests_created_test.py @@ -1,9 +1,7 @@ from unittest import mock -from prowler.providers.microsoft365.services.entra.entra_service import Group -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from prowler.providers.m365.services.entra.entra_service import Group +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_dynamic_group_for_guests_created: @@ -18,14 +16,14 @@ class Test_entra_dynamic_group_for_guests_created: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created.entra_client", + "prowler.providers.m365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created import ( + from prowler.providers.m365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created import ( entra_dynamic_group_for_guests_created, ) @@ -43,10 +41,10 @@ class Test_entra_dynamic_group_for_guests_created: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created.entra_client", + "prowler.providers.m365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created.entra_client", new=entra_client, ), ): @@ -59,7 +57,7 @@ class Test_entra_dynamic_group_for_guests_created: ) ] - from prowler.providers.microsoft365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created import ( + from prowler.providers.m365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created import ( entra_dynamic_group_for_guests_created, ) @@ -85,10 +83,10 @@ class Test_entra_dynamic_group_for_guests_created: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created.entra_client", + "prowler.providers.m365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created.entra_client", new=entra_client, ), ): @@ -101,7 +99,7 @@ class Test_entra_dynamic_group_for_guests_created: ) ] - from prowler.providers.microsoft365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created import ( + from prowler.providers.m365.services.entra.entra_dynamic_group_for_guests_created.entra_dynamic_group_for_guests_created import ( entra_dynamic_group_for_guests_created, ) diff --git a/tests/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled_test.py b/tests/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled_test.py similarity index 85% rename from tests/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled_test.py rename to tests/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled_test.py index a1c6c48f78..2bd84694ea 100644 --- a/tests/providers/microsoft365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_identity_protection_sign_in_risk_enabled/entra_identity_protection_sign_in_risk_enabled_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_identity_protection_sign_in_risk_enabled: @@ -29,14 +26,14 @@ class Test_entra_identity_protection_sign_in_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( entra_identity_protection_sign_in_risk_enabled, ) @@ -64,17 +61,17 @@ class Test_entra_identity_protection_sign_in_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( entra_identity_protection_sign_in_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -140,17 +137,17 @@ class Test_entra_identity_protection_sign_in_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( entra_identity_protection_sign_in_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -223,17 +220,17 @@ class Test_entra_identity_protection_sign_in_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( entra_identity_protection_sign_in_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -306,17 +303,17 @@ class Test_entra_identity_protection_sign_in_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_sign_in_risk_enabled.entra_identity_protection_sign_in_risk_enabled import ( entra_identity_protection_sign_in_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled_test.py b/tests/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled_test.py similarity index 85% rename from tests/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled_test.py rename to tests/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled_test.py index ead5b42d61..b251199af6 100644 --- a/tests/providers/microsoft365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_identity_protection_user_risk_enabled/entra_identity_protection_user_risk_enabled_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_identity_protection_user_risk_enabled: @@ -29,14 +26,14 @@ class Test_entra_identity_protection_user_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( entra_identity_protection_user_risk_enabled, ) @@ -64,17 +61,17 @@ class Test_entra_identity_protection_user_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( entra_identity_protection_user_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -139,17 +136,17 @@ class Test_entra_identity_protection_user_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( entra_identity_protection_user_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -221,17 +218,17 @@ class Test_entra_identity_protection_user_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( entra_identity_protection_user_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -303,17 +300,17 @@ class Test_entra_identity_protection_user_risk_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( + from prowler.providers.m365.services.entra.entra_identity_protection_user_risk_enabled.entra_identity_protection_user_risk_enabled import ( entra_identity_protection_user_risk_enabled, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked_test.py b/tests/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked_test.py similarity index 85% rename from tests/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked_test.py rename to tests/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked_test.py index 1b45102d23..b3b1a38550 100644 --- a/tests/providers/microsoft365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked_test.py +++ b/tests/providers/m365/services/entra/entra_legacy_authentication_blocked/entra_legacy_authentication_blocked_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ClientAppType, ConditionalAccessGrantControl, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_legacy_authentication_blocked: @@ -29,14 +26,14 @@ class Test_entra_legacy_authentication_blocked: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", + "prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( + from prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( entra_legacy_authentication_blocked, ) @@ -65,17 +62,17 @@ class Test_entra_legacy_authentication_blocked: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", + "prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( + from prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( entra_legacy_authentication_blocked, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -147,17 +144,17 @@ class Test_entra_legacy_authentication_blocked: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", + "prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( + from prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( entra_legacy_authentication_blocked, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -232,17 +229,17 @@ class Test_entra_legacy_authentication_blocked: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", + "prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( + from prowler.providers.m365.services.entra.entra_legacy_authentication_blocked.entra_legacy_authentication_blocked import ( entra_legacy_authentication_blocked, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication_test.py b/tests/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication_test.py similarity index 83% rename from tests/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication_test.py rename to tests/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication_test.py index d40986b56c..4f58579208 100644 --- a/tests/providers/microsoft365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication_test.py +++ b/tests/providers/m365/services/entra/entra_managed_device_required_for_authentication/entra_managed_device_required_for_authentication_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -14,10 +14,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_managed_device_required_for_authentication: @@ -28,14 +25,14 @@ class Test_entra_managed_device_required_for_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( entra_managed_device_required_for_authentication, ) @@ -63,17 +60,17 @@ class Test_entra_managed_device_required_for_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( entra_managed_device_required_for_authentication, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -137,17 +134,17 @@ class Test_entra_managed_device_required_for_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( entra_managed_device_required_for_authentication, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -219,17 +216,17 @@ class Test_entra_managed_device_required_for_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_authentication.entra_managed_device_required_for_authentication import ( entra_managed_device_required_for_authentication, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration_test.py b/tests/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration_test.py similarity index 83% rename from tests/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration_test.py rename to tests/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration_test.py index 11899eb574..a127e9859b 100644 --- a/tests/providers/microsoft365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration_test.py +++ b/tests/providers/m365/services/entra/entra_managed_device_required_for_mfa_registration/entra_managed_device_required_for_mfa_registration_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicyState, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( UserAction, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_managed_device_required_for_mfa_registration: @@ -29,14 +26,14 @@ class Test_entra_managed_device_required_for_mfa_registration: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( entra_managed_device_required_for_mfa_registration, ) @@ -64,17 +61,17 @@ class Test_entra_managed_device_required_for_mfa_registration: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( entra_managed_device_required_for_mfa_registration, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -138,17 +135,17 @@ class Test_entra_managed_device_required_for_mfa_registration: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( entra_managed_device_required_for_mfa_registration, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) @@ -220,17 +217,17 @@ class Test_entra_managed_device_required_for_mfa_registration: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", + "prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( + from prowler.providers.m365.services.entra.entra_managed_device_required_for_mfa_registration.entra_managed_device_required_for_mfa_registration import ( entra_managed_device_required_for_mfa_registration, ) - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( ConditionalAccessPolicy, ) diff --git a/tests/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled_test.py b/tests/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled_test.py similarity index 74% rename from tests/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled_test.py rename to tests/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled_test.py index bc9e5b3008..d4ec23bac3 100644 --- a/tests/providers/microsoft365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_password_hash_sync_enabled/entra_password_hash_sync_enabled_test.py @@ -1,9 +1,7 @@ from unittest import mock -from prowler.providers.microsoft365.services.entra.entra_service import Organization -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from prowler.providers.m365.services.entra.entra_service import Organization +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_password_hash_sync_enabled: @@ -13,14 +11,14 @@ class Test_entra_password_hash_sync_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( + from prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( entra_password_hash_sync_enabled, ) @@ -51,14 +49,14 @@ class Test_entra_password_hash_sync_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( + from prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( entra_password_hash_sync_enabled, ) @@ -103,14 +101,14 @@ class Test_entra_password_hash_sync_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( + from prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( entra_password_hash_sync_enabled, ) @@ -142,14 +140,14 @@ class Test_entra_password_hash_sync_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( + from prowler.providers.m365.services.entra.entra_password_hash_sync_enabled.entra_password_hash_sync_enabled import ( entra_password_hash_sync_enabled, ) diff --git a/tests/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/microsoft365_entra_policy_ensure_default_user_cannot_create_tenants_test.py b/tests/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/microsoft365_entra_policy_ensure_default_user_cannot_create_tenants_test.py similarity index 72% rename from tests/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/microsoft365_entra_policy_ensure_default_user_cannot_create_tenants_test.py rename to tests/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/microsoft365_entra_policy_ensure_default_user_cannot_create_tenants_test.py index 5c615b1da0..0e354e3e90 100644 --- a/tests/providers/microsoft365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/microsoft365_entra_policy_ensure_default_user_cannot_create_tenants_test.py +++ b/tests/providers/m365/services/entra/entra_policy_ensure_default_user_cannot_create_tenants/microsoft365_entra_policy_ensure_default_user_cannot_create_tenants_test.py @@ -1,13 +1,11 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( AuthorizationPolicy, DefaultUserRolePermissions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_policy_ensure_default_user_cannot_create_tenants: @@ -18,14 +16,14 @@ class Test_entra_policy_ensure_default_user_cannot_create_tenants: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants.entra_client", + "prowler.providers.m365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants import ( + from prowler.providers.m365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants import ( entra_policy_ensure_default_user_cannot_create_tenants, ) @@ -49,14 +47,14 @@ class Test_entra_policy_ensure_default_user_cannot_create_tenants: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants.entra_client", + "prowler.providers.m365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants import ( + from prowler.providers.m365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants import ( entra_policy_ensure_default_user_cannot_create_tenants, ) @@ -89,14 +87,14 @@ class Test_entra_policy_ensure_default_user_cannot_create_tenants: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants.entra_client", + "prowler.providers.m365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants import ( + from prowler.providers.m365.services.entra.entra_policy_ensure_default_user_cannot_create_tenants.entra_policy_ensure_default_user_cannot_create_tenants import ( entra_policy_ensure_default_user_cannot_create_tenants, ) diff --git a/tests/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/microsoft365_entra_policy_guest_invite_only_for_admin_roles_test.py b/tests/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/microsoft365_entra_policy_guest_invite_only_for_admin_roles_test.py similarity index 75% rename from tests/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/microsoft365_entra_policy_guest_invite_only_for_admin_roles_test.py rename to tests/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/microsoft365_entra_policy_guest_invite_only_for_admin_roles_test.py index 27eec2d350..b92e051e68 100644 --- a/tests/providers/microsoft365/services/entra/entra_policy_guest_invite_only_for_admin_roles/microsoft365_entra_policy_guest_invite_only_for_admin_roles_test.py +++ b/tests/providers/m365/services/entra/entra_policy_guest_invite_only_for_admin_roles/microsoft365_entra_policy_guest_invite_only_for_admin_roles_test.py @@ -1,12 +1,10 @@ import mock -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( AuthorizationPolicy, InvitationsFrom, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_policy_guest_invite_only_for_admin_roles: @@ -21,14 +19,14 @@ class Test_entra_policy_guest_invite_only_for_admin_roles: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( + from prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( entra_policy_guest_invite_only_for_admin_roles, ) @@ -54,14 +52,14 @@ class Test_entra_policy_guest_invite_only_for_admin_roles: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( + from prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( entra_policy_guest_invite_only_for_admin_roles, ) @@ -95,14 +93,14 @@ class Test_entra_policy_guest_invite_only_for_admin_roles: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( + from prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( entra_policy_guest_invite_only_for_admin_roles, ) @@ -136,14 +134,14 @@ class Test_entra_policy_guest_invite_only_for_admin_roles: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( + from prowler.providers.m365.services.entra.entra_policy_guest_invite_only_for_admin_roles.entra_policy_guest_invite_only_for_admin_roles import ( entra_policy_guest_invite_only_for_admin_roles, ) diff --git a/tests/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/microsoft365_entra_policy_guest_users_access_restrictions_test.py b/tests/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/microsoft365_entra_policy_guest_users_access_restrictions_test.py similarity index 76% rename from tests/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/microsoft365_entra_policy_guest_users_access_restrictions_test.py rename to tests/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/microsoft365_entra_policy_guest_users_access_restrictions_test.py index c0b8f7af37..7eac966f69 100644 --- a/tests/providers/microsoft365/services/entra/entra_policy_guest_users_access_restrictions/microsoft365_entra_policy_guest_users_access_restrictions_test.py +++ b/tests/providers/m365/services/entra/entra_policy_guest_users_access_restrictions/microsoft365_entra_policy_guest_users_access_restrictions_test.py @@ -1,12 +1,10 @@ from unittest import mock -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( AuthorizationPolicy, AuthPolicyRoles, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_policy_guest_users_access_restrictions: @@ -21,14 +19,14 @@ class Test_entra_policy_guest_users_access_restrictions: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( + from prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( entra_policy_guest_users_access_restrictions, ) @@ -54,14 +52,14 @@ class Test_entra_policy_guest_users_access_restrictions: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( + from prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( entra_policy_guest_users_access_restrictions, ) @@ -95,14 +93,14 @@ class Test_entra_policy_guest_users_access_restrictions: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( + from prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( entra_policy_guest_users_access_restrictions, ) @@ -136,14 +134,14 @@ class Test_entra_policy_guest_users_access_restrictions: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", + "prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( + from prowler.providers.m365.services.entra.entra_policy_guest_users_access_restrictions.entra_policy_guest_users_access_restrictions import ( entra_policy_guest_users_access_restrictions, ) diff --git a/tests/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/microsoft365_entra_policy_restricts_user_consent_for_apps_test.py b/tests/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/microsoft365_entra_policy_restricts_user_consent_for_apps_test.py similarity index 79% rename from tests/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/microsoft365_entra_policy_restricts_user_consent_for_apps_test.py rename to tests/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/microsoft365_entra_policy_restricts_user_consent_for_apps_test.py index 5dd52ebace..e31d3b9113 100644 --- a/tests/providers/microsoft365/services/entra/entra_policy_restricts_user_consent_for_apps/microsoft365_entra_policy_restricts_user_consent_for_apps_test.py +++ b/tests/providers/m365/services/entra/entra_policy_restricts_user_consent_for_apps/microsoft365_entra_policy_restricts_user_consent_for_apps_test.py @@ -1,13 +1,11 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( AuthorizationPolicy, DefaultUserRolePermissions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import set_mocked_m365_provider class Test_entra_policy_restricts_user_consent_for_apps: @@ -25,14 +23,14 @@ class Test_entra_policy_restricts_user_consent_for_apps: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client", + "prowler.providers.m365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import ( + from prowler.providers.m365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import ( entra_policy_restricts_user_consent_for_apps, ) @@ -65,14 +63,14 @@ class Test_entra_policy_restricts_user_consent_for_apps: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client", + "prowler.providers.m365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import ( + from prowler.providers.m365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import ( entra_policy_restricts_user_consent_for_apps, ) @@ -116,14 +114,14 @@ class Test_entra_policy_restricts_user_consent_for_apps: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client", + "prowler.providers.m365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import ( + from prowler.providers.m365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import ( entra_policy_restricts_user_consent_for_apps, ) diff --git a/tests/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed_test.py b/tests/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed_test.py similarity index 70% rename from tests/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed_test.py rename to tests/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed_test.py index 9d0d112b6a..d17644b134 100644 --- a/tests/providers/microsoft365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed_test.py +++ b/tests/providers/m365/services/entra/entra_thirdparty_integrated_apps_not_allowed/entra_thirdparty_integrated_apps_not_allowed_test.py @@ -1,13 +1,10 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( DefaultUserRolePermissions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_thirdparty_integrated_apps_not_allowed: @@ -18,14 +15,14 @@ class Test_entra_thirdparty_integrated_apps_not_allowed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed.entra_client", + "prowler.providers.m365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed import ( + from prowler.providers.m365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed import ( entra_thirdparty_integrated_apps_not_allowed, ) @@ -44,17 +41,17 @@ class Test_entra_thirdparty_integrated_apps_not_allowed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed.entra_client", + "prowler.providers.m365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( AuthorizationPolicy, ) - from prowler.providers.microsoft365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed import ( + from prowler.providers.m365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed import ( entra_thirdparty_integrated_apps_not_allowed, ) @@ -88,17 +85,17 @@ class Test_entra_thirdparty_integrated_apps_not_allowed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed.entra_client", + "prowler.providers.m365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_service import ( + from prowler.providers.m365.services.entra.entra_service import ( AuthorizationPolicy, ) - from prowler.providers.microsoft365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed import ( + from prowler.providers.m365.services.entra.entra_thirdparty_integrated_apps_not_allowed.entra_thirdparty_integrated_apps_not_allowed import ( entra_thirdparty_integrated_apps_not_allowed, ) diff --git a/tests/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled_test.py b/tests/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled_test.py similarity index 87% rename from tests/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled_test.py rename to tests/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled_test.py index 7552cea160..07699fdecf 100644 --- a/tests/providers/microsoft365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled_test.py +++ b/tests/providers/m365/services/entra/entra_users_mfa_enabled/entra_users_mfa_enabled_test.py @@ -1,7 +1,7 @@ from unittest import mock from uuid import uuid4 -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.services.entra.entra_service import ( ApplicationsConditions, ConditionalAccessGrantControl, ConditionalAccessPolicy, @@ -15,10 +15,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( SignInFrequencyInterval, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_entra_users_mfa_enabled: @@ -31,14 +28,14 @@ class Test_entra_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( entra_users_mfa_enabled, ) @@ -67,14 +64,14 @@ class Test_entra_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( entra_users_mfa_enabled, ) @@ -148,14 +145,14 @@ class Test_entra_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( entra_users_mfa_enabled, ) @@ -227,14 +224,14 @@ class Test_entra_users_mfa_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", + "prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled.entra_client", new=entra_client, ), ): - from prowler.providers.microsoft365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( + from prowler.providers.m365.services.entra.entra_users_mfa_enabled.entra_users_mfa_enabled import ( entra_users_mfa_enabled, ) diff --git a/tests/providers/microsoft365/services/entra/microsoft365_entra_service_test.py b/tests/providers/m365/services/entra/microsoft365_entra_service_test.py similarity index 88% rename from tests/providers/microsoft365/services/entra/microsoft365_entra_service_test.py rename to tests/providers/m365/services/entra/microsoft365_entra_service_test.py index 8c9e8128c1..98fbed8e35 100644 --- a/tests/providers/microsoft365/services/entra/microsoft365_entra_service_test.py +++ b/tests/providers/m365/services/entra/microsoft365_entra_service_test.py @@ -1,7 +1,7 @@ from unittest.mock import patch -from prowler.providers.microsoft365.models import Microsoft365IdentityInfo -from prowler.providers.microsoft365.services.entra.entra_service import ( +from prowler.providers.m365.models import M365IdentityInfo +from prowler.providers.m365.services.entra.entra_service import ( AdminConsentPolicy, AdminRoles, ApplicationsConditions, @@ -27,10 +27,7 @@ from prowler.providers.microsoft365.services.entra.entra_service import ( UserAction, UsersConditions, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider async def mock_entra_get_authorization_policy(_): @@ -153,18 +150,16 @@ async def mock_entra_get_organization(_): class Test_Entra_Service: def test_get_client(self): admincenter_client = Entra( - set_mocked_microsoft365_provider( - identity=Microsoft365IdentityInfo(tenant_domain=DOMAIN) - ) + set_mocked_m365_provider(identity=M365IdentityInfo(tenant_domain=DOMAIN)) ) assert admincenter_client.client.__class__.__name__ == "GraphServiceClient" @patch( - "prowler.providers.microsoft365.services.entra.entra_service.Entra._get_authorization_policy", + "prowler.providers.m365.services.entra.entra_service.Entra._get_authorization_policy", new=mock_entra_get_authorization_policy, ) def test_get_authorization_policy(self): - entra_client = Entra(set_mocked_microsoft365_provider()) + entra_client = Entra(set_mocked_m365_provider()) assert entra_client.authorization_policy.id == "id-1" assert entra_client.authorization_policy.name == "Name 1" assert entra_client.authorization_policy.description == "Description 1" @@ -188,11 +183,11 @@ class Test_Entra_Service: ) @patch( - "prowler.providers.microsoft365.services.entra.entra_service.Entra._get_conditional_access_policies", + "prowler.providers.m365.services.entra.entra_service.Entra._get_conditional_access_policies", new=mock_entra_get_conditional_access_policies, ) def test_get_conditional_access_policies(self): - entra_client = Entra(set_mocked_microsoft365_provider()) + entra_client = Entra(set_mocked_m365_provider()) assert entra_client.conditional_access_policies == { "id-1": ConditionalAccessPolicy( id="id-1", @@ -234,11 +229,11 @@ class Test_Entra_Service: } @patch( - "prowler.providers.microsoft365.services.entra.entra_service.Entra._get_groups", + "prowler.providers.m365.services.entra.entra_service.Entra._get_groups", new=mock_entra_get_groups, ) def test_get_groups(self): - entra_client = Entra(set_mocked_microsoft365_provider()) + entra_client = Entra(set_mocked_m365_provider()) assert len(entra_client.groups) == 2 assert entra_client.groups[0]["id"] == "id-1" assert entra_client.groups[0]["name"] == "group1" @@ -250,33 +245,33 @@ class Test_Entra_Service: assert entra_client.groups[1]["membershipRule"] == "" @patch( - "prowler.providers.microsoft365.services.entra.entra_service.Entra._get_admin_consent_policy", + "prowler.providers.m365.services.entra.entra_service.Entra._get_admin_consent_policy", new=mock_entra_get_admin_consent_policy, ) def test_get_admin_consent_policy(self): - entra_client = Entra(set_mocked_microsoft365_provider()) + entra_client = Entra(set_mocked_m365_provider()) assert entra_client.admin_consent_policy.admin_consent_enabled assert entra_client.admin_consent_policy.notify_reviewers assert entra_client.admin_consent_policy.email_reminders_to_reviewers is False assert entra_client.admin_consent_policy.duration_in_days == 30 @patch( - "prowler.providers.microsoft365.services.entra.entra_service.Entra._get_organization", + "prowler.providers.m365.services.entra.entra_service.Entra._get_organization", new=mock_entra_get_organization, ) def test_get_organization(self): - entra_client = Entra(set_mocked_microsoft365_provider()) + entra_client = Entra(set_mocked_m365_provider()) assert len(entra_client.organizations) == 1 assert entra_client.organizations[0].id == "org1" assert entra_client.organizations[0].name == "Organization 1" assert entra_client.organizations[0].on_premises_sync_enabled @patch( - "prowler.providers.microsoft365.services.entra.entra_service.Entra._get_users", + "prowler.providers.m365.services.entra.entra_service.Entra._get_users", new=mock_entra_get_users, ) def test_get_users(self): - entra_client = Entra(set_mocked_microsoft365_provider()) + entra_client = Entra(set_mocked_m365_provider()) assert len(entra_client.users) == 3 assert entra_client.users["user-1"].id == "user-1" assert entra_client.users["user-1"].name == "User 1" diff --git a/tests/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled_test.py b/tests/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled_test.py new file mode 100644 index 0000000000..0a4fc78894 --- /dev/null +++ b/tests/providers/m365/services/purview/purview_audit_log_search_enabled/purview_audit_log_search_enabled_test.py @@ -0,0 +1,82 @@ +from unittest import mock + +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider + + +class Test_purview_audit_log_search_enabled: + def test_audit_log_search_disabled(self): + purview_client = mock.MagicMock() + purview_client.audited_tenant = "audited_tenant" + purview_client.audited_domain = DOMAIN + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.purview.purview_audit_log_search_enabled.purview_audit_log_search_enabled.purview_client", + new=purview_client, + ), + ): + from prowler.providers.m365.services.purview.purview_audit_log_search_enabled.purview_audit_log_search_enabled import ( + purview_audit_log_search_enabled, + ) + from prowler.providers.m365.services.purview.purview_service import ( + AuditLogConfig, + ) + + purview_client.audit_log_config = AuditLogConfig(audit_log_search=False) + + check = purview_audit_log_search_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended == "Purview audit log search is not enabled." + ) + assert result[0].resource == purview_client.audit_log_config.dict() + assert result[0].resource_name == "Purview Settings" + assert result[0].resource_id == "purviewSettings" + assert result[0].location == "global" + purview_client.powershell.close() + + def test_audit_log_search_enabled(self): + purview_client = mock.MagicMock() + purview_client.audited_tenant = "audited_tenant" + purview_client.audited_domain = DOMAIN + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.purview.purview_audit_log_search_enabled.purview_audit_log_search_enabled.purview_client", + new=purview_client, + ), + ): + from prowler.providers.m365.services.purview.purview_audit_log_search_enabled.purview_audit_log_search_enabled import ( + purview_audit_log_search_enabled, + ) + from prowler.providers.m365.services.purview.purview_service import ( + AuditLogConfig, + ) + + purview_client.audit_log_config = AuditLogConfig(audit_log_search=True) + + check = purview_audit_log_search_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].status_extended == "Purview audit log search is enabled." + assert result[0].resource == purview_client.audit_log_config.dict() + assert result[0].resource_name == "Purview Settings" + assert result[0].resource_id == "purviewSettings" + assert result[0].location == "global" diff --git a/tests/providers/m365/services/purview/purview_service_test.py b/tests/providers/m365/services/purview/purview_service_test.py new file mode 100644 index 0000000000..9d1a9f9414 --- /dev/null +++ b/tests/providers/m365/services/purview/purview_service_test.py @@ -0,0 +1,48 @@ +from unittest import mock +from unittest.mock import patch + +from prowler.providers.m365.models import M365IdentityInfo +from prowler.providers.m365.services.purview.purview_service import ( + AuditLogConfig, + Purview, +) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider + + +def mock_get_audit_log_config(_): + return AuditLogConfig(audit_log_search=True) + + +class Test_Purview_Service: + def test_get_client(self): + with ( + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + ): + purview_client = Purview( + set_mocked_m365_provider( + identity=M365IdentityInfo(tenant_domain=DOMAIN) + ) + ) + assert purview_client.client.__class__.__name__ == "GraphServiceClient" + assert purview_client.powershell.__class__.__name__ == "M365PowerShell" + + @patch( + "prowler.providers.m365.services.purview.purview_service.Purview._get_audit_log_config", + new=mock_get_audit_log_config, + ) + def test_get_settings(self): + with ( + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + ): + purview_client = Purview( + set_mocked_m365_provider( + identity=M365IdentityInfo(tenant_domain=DOMAIN) + ) + ) + assert purview_client.audit_log_config == AuditLogConfig( + audit_log_search=True + ) diff --git a/tests/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py similarity index 78% rename from tests/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py rename to tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py index 35f8a33478..6111ff0993 100644 --- a/tests/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py @@ -1,12 +1,9 @@ from unittest import mock -from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( +from prowler.providers.m365.services.sharepoint.sharepoint_service import ( SharePointSettings, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_sharepoint_external_sharing_managed: @@ -20,14 +17,14 @@ class Test_sharepoint_external_sharing_managed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( sharepoint_external_sharing_managed, ) @@ -65,14 +62,14 @@ class Test_sharepoint_external_sharing_managed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( sharepoint_external_sharing_managed, ) @@ -110,14 +107,14 @@ class Test_sharepoint_external_sharing_managed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( sharepoint_external_sharing_managed, ) @@ -155,14 +152,14 @@ class Test_sharepoint_external_sharing_managed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( sharepoint_external_sharing_managed, ) @@ -200,14 +197,14 @@ class Test_sharepoint_external_sharing_managed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( sharepoint_external_sharing_managed, ) @@ -247,14 +244,14 @@ class Test_sharepoint_external_sharing_managed: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import ( sharepoint_external_sharing_managed, ) diff --git a/tests/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py similarity index 75% rename from tests/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py rename to tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py index 98c749cd79..f238cbf4fa 100644 --- a/tests/providers/microsoft365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py @@ -1,12 +1,9 @@ from unittest import mock -from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( +from prowler.providers.m365.services.sharepoint.sharepoint_service import ( SharePointSettings, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_sharepoint_external_sharing_restricted: @@ -20,14 +17,14 @@ class Test_sharepoint_external_sharing_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import ( sharepoint_external_sharing_restricted, ) @@ -63,14 +60,14 @@ class Test_sharepoint_external_sharing_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import ( sharepoint_external_sharing_restricted, ) @@ -108,14 +105,14 @@ class Test_sharepoint_external_sharing_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import ( + from prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import ( sharepoint_external_sharing_restricted, ) diff --git a/tests/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py b/tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py similarity index 74% rename from tests/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py rename to tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py index 0230f21db3..1386278fa6 100644 --- a/tests/providers/microsoft365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py @@ -1,12 +1,9 @@ from unittest import mock -from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( +from prowler.providers.m365.services.sharepoint.sharepoint_service import ( SharePointSettings, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_sharepoint_guest_sharing_restricted: @@ -20,14 +17,14 @@ class Test_sharepoint_guest_sharing_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import ( + from prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import ( sharepoint_guest_sharing_restricted, ) @@ -64,14 +61,14 @@ class Test_sharepoint_guest_sharing_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import ( + from prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import ( sharepoint_guest_sharing_restricted, ) @@ -110,14 +107,14 @@ class Test_sharepoint_guest_sharing_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import ( + from prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import ( sharepoint_guest_sharing_restricted, ) diff --git a/tests/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py b/tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py similarity index 73% rename from tests/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py rename to tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py index 6e0199e0b2..bf2c23a645 100644 --- a/tests/providers/microsoft365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py @@ -1,9 +1,6 @@ from unittest import mock -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider class Test_sharepoint_modern_authentication_required: @@ -17,17 +14,17 @@ class Test_sharepoint_modern_authentication_required: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import ( + from prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import ( sharepoint_modern_authentication_required, ) - from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( + from prowler.providers.m365.services.sharepoint.sharepoint_service import ( SharePointSettings, ) @@ -63,17 +60,17 @@ class Test_sharepoint_modern_authentication_required: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import ( + from prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import ( sharepoint_modern_authentication_required, ) - from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( + from prowler.providers.m365.services.sharepoint.sharepoint_service import ( SharePointSettings, ) @@ -111,14 +108,14 @@ class Test_sharepoint_modern_authentication_required: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_microsoft365_provider(), + return_value=set_mocked_m365_provider(), ), mock.patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", + "prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", new=sharepoint_client, ), ): - from prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import ( + from prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import ( sharepoint_modern_authentication_required, ) diff --git a/tests/providers/microsoft365/services/sharepoint/sharepoint_service_test.py b/tests/providers/m365/services/sharepoint/sharepoint_service_test.py similarity index 66% rename from tests/providers/microsoft365/services/sharepoint/sharepoint_service_test.py rename to tests/providers/m365/services/sharepoint/sharepoint_service_test.py index 06a220f2c8..8c3dc72598 100644 --- a/tests/providers/microsoft365/services/sharepoint/sharepoint_service_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_service_test.py @@ -1,14 +1,11 @@ from unittest.mock import patch -from prowler.providers.microsoft365.models import Microsoft365IdentityInfo -from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import ( +from prowler.providers.m365.models import M365IdentityInfo +from prowler.providers.m365.services.sharepoint.sharepoint_service import ( SharePoint, SharePointSettings, ) -from tests.providers.microsoft365.microsoft365_fixtures import ( - DOMAIN, - set_mocked_microsoft365_provider, -) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider async def mock_sharepoint_get_settings(_): @@ -23,20 +20,18 @@ async def mock_sharepoint_get_settings(_): @patch( - "prowler.providers.microsoft365.services.sharepoint.sharepoint_service.SharePoint._get_settings", + "prowler.providers.m365.services.sharepoint.sharepoint_service.SharePoint._get_settings", new=mock_sharepoint_get_settings, ) class Test_SharePoint_Service: def test_get_client(self): sharepoint_client = SharePoint( - set_mocked_microsoft365_provider( - identity=Microsoft365IdentityInfo(tenant_domain=DOMAIN) - ) + set_mocked_m365_provider(identity=M365IdentityInfo(tenant_domain=DOMAIN)) ) assert sharepoint_client.client.__class__.__name__ == "GraphServiceClient" def test_get_settings(self): - sharepoint_client = SharePoint(set_mocked_microsoft365_provider()) + sharepoint_client = SharePoint(set_mocked_m365_provider()) settings = sharepoint_client.settings assert settings.sharingCapability == "ExternalUserAndGuestSharing" assert settings.sharingAllowedDomainList == ["allowed-domain.com"] diff --git a/tests/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted_test.py b/tests/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted_test.py new file mode 100644 index 0000000000..ea8d35f189 --- /dev/null +++ b/tests/providers/m365/services/teams/teams_external_file_sharing_restricted/teams_external_file_sharing_restricted_test.py @@ -0,0 +1,121 @@ +from unittest import mock + +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider + + +class Test_teams_external_file_sharing_restricted: + def test_file_sharing_no_restricted(self): + teams_client = mock.MagicMock() + teams_client.audited_tenant = "audited_tenant" + teams_client.audited_domain = DOMAIN + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_microsoft_teams" + ), + mock.patch( + "prowler.providers.m365.services.teams.teams_external_file_sharing_restricted.teams_external_file_sharing_restricted.teams_client", + new=teams_client, + ), + ): + from prowler.providers.m365.services.teams.teams_external_file_sharing_restricted.teams_external_file_sharing_restricted import ( + teams_external_file_sharing_restricted, + ) + from prowler.providers.m365.services.teams.teams_service import ( + CloudStorageSettings, + TeamsSettings, + ) + + teams_client.teams_settings = TeamsSettings( + cloud_storage_settings=CloudStorageSettings( + allow_box=True, + allow_drop_box=True, + allow_egnyte=True, + allow_google_drive=True, + allow_share_file=True, + ) + ) + + teams_client.audit_config = {"allowed_cloud_storage_services": []} + + check = teams_external_file_sharing_restricted() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == "External file sharing is not restricted to only approved cloud storage services." + ) + assert ( + result[0].resource + == teams_client.teams_settings.cloud_storage_settings.dict() + ) + assert result[0].resource_name == "Cloud Storage Settings" + assert result[0].resource_id == "cloudStorageSettings" + assert result[0].location == "global" + + def test_file_sharing_restricted(self): + teams_client = mock.MagicMock() + teams_client.audited_tenant = "audited_tenant" + teams_client.audited_domain = DOMAIN + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_microsoft_teams" + ), + mock.patch( + "prowler.providers.m365.services.teams.teams_external_file_sharing_restricted.teams_external_file_sharing_restricted.teams_client", + new=teams_client, + ), + ): + from prowler.providers.m365.services.teams.teams_external_file_sharing_restricted.teams_external_file_sharing_restricted import ( + teams_external_file_sharing_restricted, + ) + from prowler.providers.m365.services.teams.teams_service import ( + CloudStorageSettings, + TeamsSettings, + ) + + teams_client.teams_settings = TeamsSettings( + cloud_storage_settings=CloudStorageSettings( + allow_box=True, + allow_drop_box=True, + allow_egnyte=False, + allow_google_drive=True, + allow_share_file=True, + ) + ) + + teams_client.audit_config = { + "allowed_cloud_storage_services": [ + "allow_box", + "allow_drop_box", + # "allow_egnyte", + "allow_google_drive", + "allow_share_file", + ] + } + + check = teams_external_file_sharing_restricted() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "External file sharing is restricted to only approved cloud storage services." + ) + assert ( + result[0].resource + == teams_client.teams_settings.cloud_storage_settings.dict() + ) + assert result[0].resource_name == "Cloud Storage Settings" + assert result[0].resource_id == "cloudStorageSettings" + assert result[0].location == "global" diff --git a/tests/providers/m365/services/teams/teams_service_test.py b/tests/providers/m365/services/teams/teams_service_test.py new file mode 100644 index 0000000000..73d6425433 --- /dev/null +++ b/tests/providers/m365/services/teams/teams_service_test.py @@ -0,0 +1,65 @@ +from unittest import mock +from unittest.mock import patch + +from prowler.providers.m365.models import M365IdentityInfo +from prowler.providers.m365.services.teams.teams_service import ( + CloudStorageSettings, + Teams, + TeamsSettings, +) +from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider + + +def mock_get_teams_client_configuration(_): + return TeamsSettings( + cloud_storage_settings=CloudStorageSettings( + allow_box=False, + allow_drop_box=False, + allow_egnyte=False, + allow_google_drive=False, + allow_share_file=False, + ) + ) + + +class Test_Teams_Service: + def test_get_client(self): + with ( + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_microsoft_teams" + ), + ): + teams_client = Teams( + set_mocked_m365_provider( + identity=M365IdentityInfo(tenant_domain=DOMAIN) + ) + ) + assert teams_client.client.__class__.__name__ == "GraphServiceClient" + assert teams_client.powershell.__class__.__name__ == "M365PowerShell" + teams_client.powershell.close() + + @patch( + "prowler.providers.m365.services.teams.teams_service.Teams._get_teams_client_configuration", + new=mock_get_teams_client_configuration, + ) + def test_get_settings(self): + with ( + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_microsoft_teams" + ), + ): + teams_client = Teams( + set_mocked_m365_provider( + identity=M365IdentityInfo(tenant_domain=DOMAIN) + ) + ) + assert teams_client.teams_settings == TeamsSettings( + cloud_storage_settings=CloudStorageSettings( + allow_box=False, + allow_drop_box=False, + allow_egnyte=False, + allow_google_drive=False, + allow_share_file=False, + ) + ) + teams_client.powershell.close() diff --git a/tests/providers/microsoft365/microsoft365_provider_test.py b/tests/providers/microsoft365/microsoft365_provider_test.py deleted file mode 100644 index 7658301e44..0000000000 --- a/tests/providers/microsoft365/microsoft365_provider_test.py +++ /dev/null @@ -1,312 +0,0 @@ -from unittest.mock import patch -from uuid import uuid4 - -import pytest -from azure.core.credentials import AccessToken -from azure.identity import ( - ClientSecretCredential, - DefaultAzureCredential, - InteractiveBrowserCredential, -) -from mock import MagicMock - -from prowler.config.config import ( - default_config_file_path, - default_fixer_config_file_path, - load_and_validate_config_file, -) -from prowler.providers.common.models import Connection -from prowler.providers.microsoft365.exceptions.exceptions import ( - Microsoft365HTTPResponseError, - Microsoft365NoAuthenticationMethodError, -) -from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider -from prowler.providers.microsoft365.models import ( - Microsoft365IdentityInfo, - Microsoft365RegionConfig, -) -from tests.providers.microsoft365.microsoft365_fixtures import ( - CLIENT_ID, - CLIENT_SECRET, - DOMAIN, - IDENTITY_ID, - IDENTITY_TYPE, - LOCATION, - TENANT_ID, -) - - -class TestMicrosoft365Provider: - def test_microsoft365_provider(self): - tenant_id = None - client_id = None - client_secret = None - - fixer_config = load_and_validate_config_file( - "microsoft365", default_fixer_config_file_path - ) - azure_region = "Microsoft365Global" - - with ( - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session", - return_value=ClientSecretCredential( - client_id=CLIENT_ID, - tenant_id=TENANT_ID, - client_secret=CLIENT_SECRET, - ), - ), - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_identity", - return_value=Microsoft365IdentityInfo( - identity_id=IDENTITY_ID, - identity_type=IDENTITY_TYPE, - tenant_id=TENANT_ID, - tenant_domain=DOMAIN, - location=LOCATION, - ), - ), - ): - microsoft365_provider = Microsoft365Provider( - sp_env_auth=True, - az_cli_auth=False, - browser_auth=False, - tenant_id=tenant_id, - client_id=client_id, - client_secret=client_secret, - region=azure_region, - config_path=default_config_file_path, - fixer_config=fixer_config, - ) - - assert microsoft365_provider.region_config == Microsoft365RegionConfig( - name="Microsoft365Global", - authority=None, - base_url="https://graph.microsoft.com", - credential_scopes=["https://graph.microsoft.com/.default"], - ) - assert microsoft365_provider.identity == Microsoft365IdentityInfo( - identity_id=IDENTITY_ID, - identity_type=IDENTITY_TYPE, - tenant_id=TENANT_ID, - tenant_domain=DOMAIN, - location=LOCATION, - ) - - def test_microsoft365_provider_cli_auth(self): - """Test Microsoft365 Provider initialization with CLI authentication""" - azure_region = "Microsoft365Global" - fixer_config = load_and_validate_config_file( - "microsoft365", default_fixer_config_file_path - ) - - with ( - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session", - return_value=DefaultAzureCredential( - exclude_environment_credential=True, - exclude_cli_credential=False, - exclude_managed_identity_credential=True, - exclude_visual_studio_code_credential=True, - exclude_shared_token_cache_credential=True, - exclude_powershell_credential=True, - exclude_browser_credential=True, - ), - ), - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_identity", - return_value=Microsoft365IdentityInfo( - identity_id=IDENTITY_ID, - identity_type="User", - tenant_id=TENANT_ID, - tenant_domain=DOMAIN, - location=LOCATION, - ), - ), - ): - microsoft365_provider = Microsoft365Provider( - sp_env_auth=False, - az_cli_auth=True, - browser_auth=False, - region=azure_region, - config_path=default_config_file_path, - fixer_config=fixer_config, - ) - - assert microsoft365_provider.region_config == Microsoft365RegionConfig( - name="Microsoft365Global", - authority=None, - base_url="https://graph.microsoft.com", - credential_scopes=["https://graph.microsoft.com/.default"], - ) - assert microsoft365_provider.identity == Microsoft365IdentityInfo( - identity_id=IDENTITY_ID, - identity_type="User", - tenant_id=TENANT_ID, - tenant_domain=DOMAIN, - location=LOCATION, - ) - assert isinstance(microsoft365_provider.session, DefaultAzureCredential) - - def test_microsoft365_provider_browser_auth(self): - """Test Microsoft365 Provider initialization with Browser authentication""" - azure_region = "Microsoft365Global" - fixer_config = load_and_validate_config_file( - "microsoft365", default_fixer_config_file_path - ) - - with ( - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session", - return_value=InteractiveBrowserCredential( - tenant_id=TENANT_ID, - ), - ), - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_identity", - return_value=Microsoft365IdentityInfo( - identity_id=IDENTITY_ID, - identity_type="User", - tenant_id=TENANT_ID, - tenant_domain=DOMAIN, - location=LOCATION, - ), - ), - ): - microsoft365_provider = Microsoft365Provider( - sp_env_auth=False, - az_cli_auth=False, - browser_auth=True, - tenant_id=TENANT_ID, - region=azure_region, - config_path=default_config_file_path, - fixer_config=fixer_config, - ) - - assert microsoft365_provider.region_config == Microsoft365RegionConfig( - name="Microsoft365Global", - authority=None, - base_url="https://graph.microsoft.com", - credential_scopes=["https://graph.microsoft.com/.default"], - ) - assert microsoft365_provider.identity == Microsoft365IdentityInfo( - identity_id=IDENTITY_ID, - identity_type="User", - tenant_id=TENANT_ID, - tenant_domain=DOMAIN, - location=LOCATION, - ) - assert isinstance( - microsoft365_provider.session, InteractiveBrowserCredential - ) - - def test_test_connection_browser_auth(self): - with ( - patch( - "prowler.providers.microsoft365.microsoft365_provider.DefaultAzureCredential" - ) as mock_default_credential, - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session" - ) as mock_setup_session, - patch( - "prowler.providers.microsoft365.microsoft365_provider.GraphServiceClient" - ) as mock_graph_client, - ): - # Mock the return value of DefaultAzureCredential - mock_credentials = MagicMock() - mock_credentials.get_token.return_value = AccessToken( - token="fake_token", expires_on=9999999999 - ) - mock_default_credential.return_value = mock_credentials - - # Mock setup_session to return a mocked session object - mock_session = MagicMock() - mock_setup_session.return_value = mock_session - - # Mock GraphServiceClient to avoid real API calls - mock_client = MagicMock() - mock_graph_client.return_value = mock_client - - test_connection = Microsoft365Provider.test_connection( - browser_auth=True, - tenant_id=str(uuid4()), - region="Microsoft365Global", - raise_on_exception=False, - ) - - assert isinstance(test_connection, Connection) - assert test_connection.is_connected - assert test_connection.error is None - - def test_test_connection_tenant_id_client_id_client_secret(self): - with ( - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session" - ) as mock_setup_session, - patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.validate_static_credentials" - ) as mock_validate_static_credentials, - ): - # Mock setup_session to return a mocked session object - mock_session = MagicMock() - mock_setup_session.return_value = mock_session - - # Mock ValidateStaticCredentials to avoid real API calls - mock_validate_static_credentials.return_value = None - - test_connection = Microsoft365Provider.test_connection( - tenant_id=str(uuid4()), - region="Microsoft365Global", - raise_on_exception=False, - client_id=str(uuid4()), - client_secret=str(uuid4()), - ) - - assert isinstance(test_connection, Connection) - assert test_connection.is_connected - assert test_connection.error is None - - def test_test_connection_with_httpresponseerror(self): - with patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session" - ) as mock_setup_session: - mock_setup_session.side_effect = Microsoft365HTTPResponseError( - file="test_file", original_exception="Simulated HttpResponseError" - ) - - with pytest.raises(Microsoft365HTTPResponseError) as exception: - Microsoft365Provider.test_connection( - az_cli_auth=True, - raise_on_exception=True, - ) - - assert exception.type == Microsoft365HTTPResponseError - assert ( - exception.value.args[0] - == "[6003] Error in HTTP response from Microsoft365 - Simulated HttpResponseError" - ) - - def test_test_connection_with_exception(self): - with patch( - "prowler.providers.microsoft365.microsoft365_provider.Microsoft365Provider.setup_session" - ) as mock_setup_session: - mock_setup_session.side_effect = Exception("Simulated Exception") - - with pytest.raises(Exception) as exception: - Microsoft365Provider.test_connection( - sp_env_auth=True, - raise_on_exception=True, - ) - - assert exception.type is Exception - assert exception.value.args[0] == "Simulated Exception" - - def test_test_connection_without_any_method(self): - with pytest.raises(Microsoft365NoAuthenticationMethodError) as exception: - Microsoft365Provider.test_connection() - - assert exception.type == Microsoft365NoAuthenticationMethodError - assert ( - "Microsoft365 provider requires at least one authentication method set: [--az-cli-auth | --sp-env-auth | --browser-auth]" - in exception.value.args[0] - ) diff --git a/util/generate_compliance_json_from_csv_for_cis40_microsoft365.py b/util/generate_compliance_json_from_csv_for_cis40_microsoft365.py index c6ba8c101f..11a1dd8cca 100644 --- a/util/generate_compliance_json_from_csv_for_cis40_microsoft365.py +++ b/util/generate_compliance_json_from_csv_for_cis40_microsoft365.py @@ -2,7 +2,7 @@ import csv import json import sys -# Convert a CSV file following the CIS 4.0 Microsoft365 Benchmark into a Prowler v3.0 Compliance JSON file +# Convert a CSV file following the CIS 4.0 M365 Benchmark into a Prowler v3.0 Compliance JSON file # CSV fields: # Section #,Recommendation #,Profile,Title,Assessment Status,Description,Rationale Statement,Impact Statement,Remediation Procedure,Audit Procedure,Additional Information,CIS Controls,CIS Safeguards 1 (v8),CIS Safeguards 2 (v8),CIS Safeguards 3 (v8),v8 IG1,v8 IG2,v8 IG3,CIS Safeguards 1 (v7),CIS Safeguards 2 (v7),CIS Safeguards 3 (v7),v7 IG1,v7 IG2,v7 IG3,References,Default Value @@ -68,7 +68,7 @@ except UnicodeDecodeError: ) # Save the output JSON file -with open("cis_4.0_microsoft365.json", "w", encoding="utf-8") as outfile: +with open("cis_4.0_m365.json", "w", encoding="utf-8") as outfile: json.dump(output, outfile, indent=4, ensure_ascii=False) print("Archivo JSON generado exitosamente.")