diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 589f76323c8..9cf9ec6c181 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - ASD Essential Eight Maturity Model compliance framework for AWS (Maturity Level One, Nov 2023) [(#10808)](https://github.com/prowler-cloud/prowler/pull/10808) - Update Vercel checks to return personalized finding status extended depending on billing plan and classify them with billing-plan categories [(#10663)](https://github.com/prowler-cloud/prowler/pull/10663) - `bedrock_prompt_management_exists` check for AWS provider [(#10878)](https://github.com/prowler-cloud/prowler/pull/10878) +- 8 Gmail attachment safety and spoofing protection checks for Google Workspace provider using the Cloud Identity Policy API [(#10980)](https://github.com/prowler-cloud/prowler/pull/10980) ### 🔄 Changed diff --git a/prowler/compliance/googleworkspace/cis_1.3_googleworkspace.json b/prowler/compliance/googleworkspace/cis_1.3_googleworkspace.json index c236a1f6434..1e44d8a9a56 100644 --- a/prowler/compliance/googleworkspace/cis_1.3_googleworkspace.json +++ b/prowler/compliance/googleworkspace/cis_1.3_googleworkspace.json @@ -653,7 +653,9 @@ { "Id": "3.1.3.4.1.1", "Description": "Ensure protection against encrypted attachments from untrusted senders is enabled", - "Checks": [], + "Checks": [ + "gmail_encrypted_attachment_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -674,7 +676,9 @@ { "Id": "3.1.3.4.1.2", "Description": "Ensure protection against attachments with scripts from untrusted senders is enabled", - "Checks": [], + "Checks": [ + "gmail_script_attachment_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -695,7 +699,9 @@ { "Id": "3.1.3.4.1.3", "Description": "Ensure protection against anomalous attachment types in emails is enabled", - "Checks": [], + "Checks": [ + "gmail_anomalous_attachment_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -785,7 +791,9 @@ { "Id": "3.1.3.4.3.1", "Description": "Ensure protection against domain spoofing based on similar domain names is enabled", - "Checks": [], + "Checks": [ + "gmail_domain_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -806,7 +814,9 @@ { "Id": "3.1.3.4.3.2", "Description": "Ensure protection against spoofing of employee names is enabled", - "Checks": [], + "Checks": [ + "gmail_employee_name_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -827,7 +837,9 @@ { "Id": "3.1.3.4.3.3", "Description": "Ensure protection against inbound emails spoofing your domain is enabled", - "Checks": [], + "Checks": [ + "gmail_inbound_domain_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -848,7 +860,9 @@ { "Id": "3.1.3.4.3.4", "Description": "Ensure protection against any unauthenticated emails is enabled", - "Checks": [], + "Checks": [ + "gmail_unauthenticated_email_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", @@ -869,7 +883,9 @@ { "Id": "3.1.3.4.3.5", "Description": "Ensure groups are protected from inbound emails spoofing your domain", - "Checks": [], + "Checks": [ + "gmail_groups_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "3 Apps", diff --git a/prowler/compliance/googleworkspace/cisa_scuba_0.6_googleworkspace.json b/prowler/compliance/googleworkspace/cisa_scuba_0.6_googleworkspace.json index 607d7018189..9d99ee577c3 100644 --- a/prowler/compliance/googleworkspace/cisa_scuba_0.6_googleworkspace.json +++ b/prowler/compliance/googleworkspace/cisa_scuba_0.6_googleworkspace.json @@ -649,7 +649,9 @@ { "Id": "GWS.GMAIL.5.1", "Description": "Protect against encrypted attachments from untrusted senders SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_encrypted_attachment_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -662,7 +664,9 @@ { "Id": "GWS.GMAIL.5.2", "Description": "Protect against attachments with scripts from untrusted senders SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_script_attachment_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -675,7 +679,9 @@ { "Id": "GWS.GMAIL.5.3", "Description": "Protect against anomalous attachment types in emails SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_anomalous_attachment_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -798,7 +804,9 @@ { "Id": "GWS.GMAIL.7.1", "Description": "Protect against domain spoofing based on similar domain names SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_domain_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -811,7 +819,9 @@ { "Id": "GWS.GMAIL.7.2", "Description": "Protect against spoofing of employee names SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_employee_name_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -824,7 +834,9 @@ { "Id": "GWS.GMAIL.7.3", "Description": "Protect against inbound emails spoofing your domain SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_inbound_domain_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -837,7 +849,9 @@ { "Id": "GWS.GMAIL.7.4", "Description": "Protect against any unauthenticated emails SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_unauthenticated_email_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", @@ -850,7 +864,9 @@ { "Id": "GWS.GMAIL.7.5", "Description": "Protect your Groups from inbound emails spoofing your domain SHALL be enabled", - "Checks": [], + "Checks": [ + "gmail_groups_spoofing_protection_enabled" + ], "Attributes": [ { "Section": "Gmail", diff --git a/tests/providers/googleworkspace/services/gmail/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled.metadata.json new file mode 100644 index 00000000000..77a1c68b385 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled.metadata.json @@ -0,0 +1,40 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_anomalous_attachment_protection_enabled", + "CheckTitle": "Protection against anomalous attachment types in emails is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when emails contain anomalous attachment types. Unusual file types that are uncommon for the sender or organization may indicate an attempt to deliver malware through less-scrutinized formats.", + "Risk": "Without protection against anomalous attachment types, users may receive **emails with unusual file formats** that are designed to bypass standard security filters. Attackers may use **uncommon file extensions or MIME types** to deliver malware that evades signature-based detection.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/7676854", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Attachments**\n4. Check **Protect against anomalous attachment types in emails**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against anomalous attachment types in emails and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_anomalous_attachment_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_encrypted_attachment_protection_enabled", + "gmail_script_attachment_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled.py new file mode 100644 index 00000000000..5bbb732f06a --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled.py @@ -0,0 +1,71 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_anomalous_attachment_protection_enabled(Check): + """Check that protection against anomalous attachment types in emails is enabled. + + This check verifies that Gmail is configured to take action on + emails containing unusual attachment types, helping prevent + malware delivery via uncommon file formats. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.enable_anomalous_attachment_protection + consequence = ( + gmail_client.policies.anomalous_attachment_protection_consequence + ) + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against anomalous attachment types in emails " + f"is disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif enabled is None: + report.status = "FAIL" + report.status_extended = ( + f"Protection against anomalous attachment types in emails " + f"is not configured and uses Google's insecure default " + f"(disabled) in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against anomalous attachment types in emails " + f"is set to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against anomalous attachment types in emails " + f"is enabled in domain " + f"{gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against anomalous attachment types in emails " + f"is enabled with consequence '{consequence}' " + f"in domain {gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/googleworkspace/services/gmail/gmail_auto_forwarding_disabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_auto_forwarding_disabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled.metadata.json new file mode 100644 index 00000000000..4ae8bfb3c0e --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_domain_spoofing_protection_enabled", + "CheckTitle": "Protection against domain spoofing based on similar domain names is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when emails appear to come from domain names that look similar to the organization's domain. Lookalike domains are a common phishing technique used to trick users into trusting malicious messages.", + "Risk": "Without protection against domain spoofing based on similar domain names, users may receive **phishing emails from lookalike domains** (e.g., examp1e.com instead of example.com) that appear legitimate. This enables **credential theft, malware delivery, and business email compromise** attacks.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/9157861", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Spoofing and authentication**\n4. Check **Protect against domain spoofing based on similar domain names**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against domain spoofing based on similar domain names and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_domain_spoofing_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_employee_name_spoofing_protection_enabled", + "gmail_inbound_domain_spoofing_protection_enabled", + "gmail_unauthenticated_email_protection_enabled", + "gmail_groups_spoofing_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled.py new file mode 100644 index 00000000000..fe275d4564e --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled.py @@ -0,0 +1,62 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_domain_spoofing_protection_enabled(Check): + """Check that protection against domain spoofing based on similar domain names is enabled. + + This check verifies that Gmail is configured to take action on + emails that appear to come from similar-looking domain names, + helping prevent phishing via domain impersonation. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.detect_domain_name_spoofing + consequence = gmail_client.policies.domain_spoofing_consequence + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against domain spoofing based on similar " + f"domain names is disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against domain spoofing based on similar " + f"domain names is set to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against domain spoofing based on similar " + f"domain names uses Google's secure default configuration " + f"(enabled) in domain " + f"{gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against domain spoofing based on similar " + f"domain names is enabled with consequence " + f"'{consequence}' in domain " + f"{gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/googleworkspace/services/gmail/gmail_comprehensive_mail_storage_enabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_comprehensive_mail_storage_enabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled.metadata.json new file mode 100644 index 00000000000..b72137019a1 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_employee_name_spoofing_protection_enabled", + "CheckTitle": "Protection against spoofing of employee names is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when the sender's display name matches an employee's name but the email comes from an external address. This is a common social engineering technique where attackers impersonate colleagues or executives.", + "Risk": "Without protection against employee name spoofing, users may receive **emails that appear to come from colleagues or executives** but are actually from external attackers. This enables **business email compromise (BEC)**, **wire fraud**, and **social engineering attacks** that exploit trust relationships.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/9157861", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Spoofing and authentication**\n4. Check **Protect against spoofing of employee names**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against spoofing of employee names and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_employee_name_spoofing_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_domain_spoofing_protection_enabled", + "gmail_inbound_domain_spoofing_protection_enabled", + "gmail_unauthenticated_email_protection_enabled", + "gmail_groups_spoofing_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled.py new file mode 100644 index 00000000000..f5131842dd6 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled.py @@ -0,0 +1,60 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_employee_name_spoofing_protection_enabled(Check): + """Check that protection against spoofing of employee names is enabled. + + This check verifies that Gmail is configured to take action on + emails where the sender name matches an employee name but comes + from an external address, helping prevent social engineering attacks. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.detect_employee_name_spoofing + consequence = gmail_client.policies.employee_name_spoofing_consequence + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against spoofing of employee names is " + f"disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against spoofing of employee names is set " + f"to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against spoofing of employee names uses " + f"Google's secure default configuration (enabled) " + f"in domain {gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against spoofing of employee names is " + f"enabled with consequence '{consequence}' in domain " + f"{gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/googleworkspace/services/gmail/gmail_enhanced_pre_delivery_scanning_enabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_enhanced_pre_delivery_scanning_enabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled.metadata.json new file mode 100644 index 00000000000..459ce1f5394 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled.metadata.json @@ -0,0 +1,40 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_encrypted_attachment_protection_enabled", + "CheckTitle": "Protection against encrypted attachments from untrusted senders is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when an encrypted attachment is received from an untrusted sender. Encrypted attachments cannot be scanned for malware by security filters, making them a common vector for delivering malicious payloads.", + "Risk": "Without protection against encrypted attachments from untrusted senders, users may receive **password-protected archives containing malware** that bypass standard content scanning. Attackers commonly use encrypted attachments to evade detection and deliver **ransomware, trojans, or other malicious payloads**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/7676854", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Attachments**\n4. Check **Protect against encrypted attachments from untrusted senders**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against encrypted attachments from untrusted senders and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_encrypted_attachment_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_script_attachment_protection_enabled", + "gmail_anomalous_attachment_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled.py new file mode 100644 index 00000000000..6a98dd00887 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled.py @@ -0,0 +1,63 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_encrypted_attachment_protection_enabled(Check): + """Check that protection against encrypted attachments from untrusted senders is enabled. + + This check verifies that Gmail is configured to take action on + encrypted attachments from untrusted senders, helping prevent + malware delivery via password-protected archives. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.enable_encrypted_attachment_protection + consequence = ( + gmail_client.policies.encrypted_attachment_protection_consequence + ) + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against encrypted attachments from untrusted " + f"senders is disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against encrypted attachments from untrusted " + f"senders is set to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against encrypted attachments from untrusted " + f"senders uses Google's secure default configuration " + f"(enabled) in domain " + f"{gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against encrypted attachments from untrusted " + f"senders is enabled with consequence '{consequence}' " + f"in domain {gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/googleworkspace/services/gmail/gmail_external_image_scanning_enabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_external_image_scanning_enabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled.metadata.json new file mode 100644 index 00000000000..0c3dd647611 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_groups_spoofing_protection_enabled", + "CheckTitle": "Groups are protected from inbound emails spoofing your domain", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when groups receive inbound emails that spoof the organization's domain. Google Groups are a high-value target because a single spoofed message can reach many recipients at once.", + "Risk": "Without protection of groups from domain-spoofing emails, attackers can send **spoofed messages to group mailboxes** that appear to originate from the organization. Since groups distribute to many recipients, a single spoofed email can enable **mass phishing, social engineering, or misinformation** campaigns across the organization.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/9157861", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Spoofing and authentication**\n4. Check **Protect your Groups from inbound emails spoofing your domain**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection of groups from inbound emails spoofing your domain and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_groups_spoofing_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_domain_spoofing_protection_enabled", + "gmail_employee_name_spoofing_protection_enabled", + "gmail_inbound_domain_spoofing_protection_enabled", + "gmail_unauthenticated_email_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled.py new file mode 100644 index 00000000000..866a53989d3 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled.py @@ -0,0 +1,81 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_groups_spoofing_protection_enabled(Check): + """Check that groups are protected from inbound emails spoofing your domain. + + This check verifies that Gmail is configured to take action on + inbound emails to groups that spoof the organization's domain, + helping prevent impersonation attacks targeting group mailboxes. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.detect_groups_spoofing + consequence = gmail_client.policies.groups_spoofing_consequence + visibility_type = gmail_client.policies.groups_spoofing_visibility_type + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection of groups from inbound emails spoofing your " + f"domain is disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif enabled is None: + report.status = "FAIL" + report.status_extended = ( + f"Protection of groups from inbound emails spoofing your " + f"domain is not configured and uses Google's insecure " + f"default (disabled) in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection of groups from inbound emails spoofing your " + f"domain is set to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + scope = ( + "private groups only" + if visibility_type == "PRIVATE_GROUPS_ONLY" + else "all groups" + ) + report.status_extended = ( + f"Protection of groups from inbound emails spoofing your " + f"domain is enabled for {scope} in domain " + f"{gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + scope = ( + "private groups only" + if visibility_type == "PRIVATE_GROUPS_ONLY" + else "all groups" + ) + report.status_extended = ( + f"Protection of groups from inbound emails spoofing your " + f"domain is enabled for {scope} with consequence " + f"'{consequence}' in domain " + f"{gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/googleworkspace/services/gmail/gmail_mail_delegation_disabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_mail_delegation_disabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled.metadata.json new file mode 100644 index 00000000000..9e285621c87 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_inbound_domain_spoofing_protection_enabled", + "CheckTitle": "Protection against inbound emails spoofing your domain is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when inbound emails spoof the organization's own domain. This protects against attackers sending emails that appear to originate from within the organization but are actually external.", + "Risk": "Without protection against inbound domain spoofing, users may receive **emails that appear to come from their own organization** but are sent by external attackers. This enables **internal impersonation**, **phishing**, and **business email compromise** attacks that exploit trust in internal communications.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/9157861", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Spoofing and authentication**\n4. Check **Protect against inbound emails spoofing your domain**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against inbound emails spoofing your domain and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_inbound_domain_spoofing_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_domain_spoofing_protection_enabled", + "gmail_employee_name_spoofing_protection_enabled", + "gmail_unauthenticated_email_protection_enabled", + "gmail_groups_spoofing_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled.py new file mode 100644 index 00000000000..f637759a55c --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled.py @@ -0,0 +1,60 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_inbound_domain_spoofing_protection_enabled(Check): + """Check that protection against inbound emails spoofing your domain is enabled. + + This check verifies that Gmail is configured to take action on + inbound emails that spoof the organization's own domain, helping + prevent impersonation of internal senders. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.detect_inbound_domain_spoofing + consequence = gmail_client.policies.inbound_domain_spoofing_consequence + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against inbound emails spoofing your domain " + f"is disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against inbound emails spoofing your domain " + f"is set to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against inbound emails spoofing your domain " + f"uses Google's secure default configuration (enabled) " + f"in domain {gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against inbound emails spoofing your domain " + f"is enabled with consequence '{consequence}' " + f"in domain {gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/tests/providers/googleworkspace/services/gmail/gmail_per_user_outbound_gateway_disabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_per_user_outbound_gateway_disabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled.metadata.json new file mode 100644 index 00000000000..fc2a3af1b01 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled.metadata.json @@ -0,0 +1,40 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_script_attachment_protection_enabled", + "CheckTitle": "Protection against attachments with scripts from untrusted senders is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when an attachment containing scripts is received from an untrusted sender. Script-bearing attachments (e.g., .js, .vbs, .ps1) are a common malware delivery mechanism.", + "Risk": "Without protection against script-bearing attachments from untrusted senders, users may receive **files containing malicious scripts** that can execute harmful code when opened. Attackers commonly use script attachments to deliver **malware, backdoors, or credential stealers**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/7676854", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Attachments**\n4. Check **Protect against attachments with scripts from untrusted senders**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against attachments with scripts from untrusted senders and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_script_attachment_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_encrypted_attachment_protection_enabled", + "gmail_anomalous_attachment_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled.py new file mode 100644 index 00000000000..ec34df7ceed --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled.py @@ -0,0 +1,62 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_script_attachment_protection_enabled(Check): + """Check that protection against attachments with scripts from untrusted senders is enabled. + + This check verifies that Gmail is configured to take action on + attachments containing scripts from untrusted senders, helping + prevent malware delivery via script-bearing files. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.enable_script_attachment_protection + consequence = gmail_client.policies.script_attachment_protection_consequence + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against attachments with scripts from " + f"untrusted senders is disabled in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against attachments with scripts from " + f"untrusted senders is set to take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against attachments with scripts from " + f"untrusted senders uses Google's secure default " + f"configuration (enabled) in domain " + f"{gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against attachments with scripts from " + f"untrusted senders is enabled with consequence " + f"'{consequence}' in domain " + f"{gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_service.py b/prowler/providers/googleworkspace/services/gmail/gmail_service.py index eecf0c1884d..ed9dc718039 100644 --- a/prowler/providers/googleworkspace/services/gmail/gmail_service.py +++ b/prowler/providers/googleworkspace/services/gmail/gmail_service.py @@ -57,12 +57,21 @@ def _fetch_gmail_policies(self): logger.debug("Gmail mail delegation setting fetched.") elif setting_type == "gmail.email_attachment_safety": + self.policies.enable_encrypted_attachment_protection = ( + value.get("enableEncryptedAttachmentProtection") + ) self.policies.encrypted_attachment_protection_consequence = value.get( "encryptedAttachmentProtectionConsequence" ) + self.policies.enable_script_attachment_protection = ( + value.get("enableAttachmentWithScriptsProtection") + ) self.policies.script_attachment_protection_consequence = ( value.get("scriptAttachmentProtectionConsequence") ) + self.policies.enable_anomalous_attachment_protection = ( + value.get("enableAnomalousAttachmentProtection") + ) self.policies.anomalous_attachment_protection_consequence = value.get( "anomalousAttachmentProtectionConsequence" ) @@ -83,18 +92,36 @@ def _fetch_gmail_policies(self): ) elif setting_type == "gmail.spoofing_and_authentication": + self.policies.detect_domain_name_spoofing = value.get( + "detectDomainNameSpoofing" + ) self.policies.domain_spoofing_consequence = value.get( "domainSpoofingConsequence" ) + self.policies.detect_employee_name_spoofing = value.get( + "detectEmployeeNameSpoofing" + ) self.policies.employee_name_spoofing_consequence = ( value.get("employeeNameSpoofingConsequence") ) + self.policies.detect_inbound_domain_spoofing = value.get( + "detectDomainSpoofingFromUnauthenticatedSenders" + ) self.policies.inbound_domain_spoofing_consequence = ( value.get("inboundDomainSpoofingConsequence") ) + self.policies.detect_unauthenticated_emails = value.get( + "detectUnauthenticatedEmails" + ) self.policies.unauthenticated_email_consequence = value.get( "unauthenticatedEmailConsequence" ) + self.policies.detect_groups_spoofing = value.get( + "detectGroupsSpoofing" + ) + self.policies.groups_spoofing_visibility_type = value.get( + "groupsSpoofingVisibilityType" + ) self.policies.groups_spoofing_consequence = value.get( "groupsSpoofingConsequence" ) @@ -177,8 +204,11 @@ class GmailPolicies(BaseModel): enable_mail_delegation: Optional[bool] = None # gmail.email_attachment_safety + enable_encrypted_attachment_protection: Optional[bool] = None encrypted_attachment_protection_consequence: Optional[str] = None + enable_script_attachment_protection: Optional[bool] = None script_attachment_protection_consequence: Optional[str] = None + enable_anomalous_attachment_protection: Optional[bool] = None anomalous_attachment_protection_consequence: Optional[str] = None # gmail.links_and_external_images @@ -187,10 +217,16 @@ class GmailPolicies(BaseModel): enable_aggressive_warnings_on_untrusted_links: Optional[bool] = None # gmail.spoofing_and_authentication + detect_domain_name_spoofing: Optional[bool] = None domain_spoofing_consequence: Optional[str] = None + detect_employee_name_spoofing: Optional[bool] = None employee_name_spoofing_consequence: Optional[str] = None + detect_inbound_domain_spoofing: Optional[bool] = None inbound_domain_spoofing_consequence: Optional[str] = None + detect_unauthenticated_emails: Optional[bool] = None unauthenticated_email_consequence: Optional[str] = None + detect_groups_spoofing: Optional[bool] = None + groups_spoofing_visibility_type: Optional[str] = None groups_spoofing_consequence: Optional[str] = None # gmail.pop_access diff --git a/tests/providers/googleworkspace/services/gmail/gmail_pop_imap_access_disabled/__init__.py b/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/__init__.py similarity index 100% rename from tests/providers/googleworkspace/services/gmail/gmail_pop_imap_access_disabled/__init__.py rename to prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/__init__.py diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled.metadata.json b/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled.metadata.json new file mode 100644 index 00000000000..61990802240 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "googleworkspace", + "CheckID": "gmail_unauthenticated_email_protection_enabled", + "CheckTitle": "Protection against any unauthenticated emails is enabled", + "CheckType": [], + "ServiceName": "gmail", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "NotDefined", + "ResourceGroup": "collaboration", + "Description": "Verifies that Gmail is configured to take a protective action (such as moving to spam, quarantining, or showing a warning) when emails are not authenticated via SPF or DKIM. Unauthenticated emails cannot be verified as originating from the claimed sender, making them more likely to be spoofed or forged.", + "Risk": "Without protection against unauthenticated emails, users may receive **spoofed or forged messages** that fail SPF and DKIM checks but are still delivered normally. This enables **phishing**, **spam**, and **impersonation attacks** that exploit the lack of sender verification.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.google.com/a/answer/9157861", + "https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Gmail**\n3. Click **Safety** > **Spoofing and authentication**\n4. Check **Protect against any unauthenticated emails**\n5. Select the desired action (e.g., Move email to spam)\n6. Click **Save**", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable protection against any unauthenticated emails and configure an appropriate action such as moving to spam or quarantining.", + "Url": "https://hub.prowler.com/check/gmail_unauthenticated_email_protection_enabled" + } + }, + "Categories": [ + "email-security" + ], + "DependsOn": [], + "RelatedTo": [ + "gmail_domain_spoofing_protection_enabled", + "gmail_employee_name_spoofing_protection_enabled", + "gmail_inbound_domain_spoofing_protection_enabled", + "gmail_groups_spoofing_protection_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled.py new file mode 100644 index 00000000000..86d2339bff1 --- /dev/null +++ b/prowler/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled.py @@ -0,0 +1,67 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGoogleWorkspace +from prowler.providers.googleworkspace.services.gmail.gmail_client import gmail_client + + +class gmail_unauthenticated_email_protection_enabled(Check): + """Check that protection against any unauthenticated emails is enabled. + + This check verifies that Gmail is configured to take action on + emails that are not authenticated via SPF or DKIM, helping prevent + delivery of spoofed or forged messages. + """ + + def execute(self) -> List[CheckReportGoogleWorkspace]: + findings = [] + + if gmail_client.policies_fetched: + report = CheckReportGoogleWorkspace( + metadata=self.metadata(), + resource=gmail_client.provider.domain_resource, + ) + + enabled = gmail_client.policies.detect_unauthenticated_emails + consequence = gmail_client.policies.unauthenticated_email_consequence + + if enabled is False: + report.status = "FAIL" + report.status_extended = ( + f"Protection against unauthenticated emails is disabled " + f"in domain {gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif enabled is None: + report.status = "FAIL" + report.status_extended = ( + f"Protection against unauthenticated emails is not " + f"configured and uses Google's insecure default " + f"(disabled) in domain " + f"{gmail_client.provider.identity.domain}. " + f"Enable the protection and configure a protective action." + ) + elif consequence == "NO_ACTION": + report.status = "FAIL" + report.status_extended = ( + f"Protection against unauthenticated emails is set to " + f"take no action in domain " + f"{gmail_client.provider.identity.domain}. " + f"A protective action should be configured." + ) + elif consequence is None: + report.status = "PASS" + report.status_extended = ( + f"Protection against unauthenticated emails is enabled " + f"in domain {gmail_client.provider.identity.domain}." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Protection against unauthenticated emails is enabled " + f"with consequence '{consequence}' in domain " + f"{gmail_client.provider.identity.domain}." + ) + + findings.append(report) + + return findings diff --git a/prowler/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled.py b/prowler/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled.py index 4bf1dbdcdfa..82cc9a1153d 100644 --- a/prowler/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled.py +++ b/prowler/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled.py @@ -32,11 +32,13 @@ def execute(self) -> List[CheckReportGoogleWorkspace]: f"in domain {gmail_client.provider.identity.domain}." ) elif warnings_enabled is None: - report.status = "PASS" + report.status = "FAIL" report.status_extended = ( - f"Warning prompts for clicks on untrusted domain links uses Google's " - f"secure default configuration (enabled) " - f"in domain {gmail_client.provider.identity.domain}." + f"Warning prompts for clicks on untrusted domain links " + f"are not configured and use Google's insecure default " + f"(disabled) in domain " + f"{gmail_client.provider.identity.domain}. " + f"Untrusted link warnings should be enabled to protect users." ) else: report.status = "FAIL" diff --git a/tests/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled_test.py new file mode 100644 index 00000000000..c0b5ac2dbcf --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_anomalous_attachment_protection_enabled/gmail_anomalous_attachment_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailAnomalousAttachmentProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled import ( + gmail_anomalous_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_anomalous_attachment_protection=True, + anomalous_attachment_protection_consequence="WARNING", + ) + + check = gmail_anomalous_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "WARNING" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled import ( + gmail_anomalous_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_anomalous_attachment_protection=True, + anomalous_attachment_protection_consequence="NO_ACTION", + ) + + check = gmail_anomalous_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled import ( + gmail_anomalous_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_anomalous_attachment_protection=False, + anomalous_attachment_protection_consequence="WARNING", + ) + + check = gmail_anomalous_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_fail_no_policy_set(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled import ( + gmail_anomalous_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_anomalous_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "insecure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_anomalous_attachment_protection_enabled.gmail_anomalous_attachment_protection_enabled import ( + gmail_anomalous_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_anomalous_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled_test.py new file mode 100644 index 00000000000..db16061744c --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_domain_spoofing_protection_enabled/gmail_domain_spoofing_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailDomainSpoofingProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled import ( + gmail_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_domain_name_spoofing=True, + domain_spoofing_consequence="SPAM_FOLDER", + ) + + check = gmail_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "SPAM_FOLDER" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled import ( + gmail_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_domain_name_spoofing=True, + domain_spoofing_consequence="NO_ACTION", + ) + + check = gmail_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled import ( + gmail_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_domain_name_spoofing=False, + domain_spoofing_consequence="WARNING", + ) + + check = gmail_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_pass_using_default(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled import ( + gmail_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "secure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_domain_spoofing_protection_enabled.gmail_domain_spoofing_protection_enabled import ( + gmail_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled_test.py new file mode 100644 index 00000000000..d8a204a6dea --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_employee_name_spoofing_protection_enabled/gmail_employee_name_spoofing_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailEmployeeNameSpoofingProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled import ( + gmail_employee_name_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_employee_name_spoofing=True, + employee_name_spoofing_consequence="SPAM_FOLDER", + ) + + check = gmail_employee_name_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "SPAM_FOLDER" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled import ( + gmail_employee_name_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_employee_name_spoofing=True, + employee_name_spoofing_consequence="NO_ACTION", + ) + + check = gmail_employee_name_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled import ( + gmail_employee_name_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_employee_name_spoofing=False, + employee_name_spoofing_consequence="WARNING", + ) + + check = gmail_employee_name_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_pass_using_default(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled import ( + gmail_employee_name_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_employee_name_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "secure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_employee_name_spoofing_protection_enabled.gmail_employee_name_spoofing_protection_enabled import ( + gmail_employee_name_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_employee_name_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled_test.py new file mode 100644 index 00000000000..5b86095b0d3 --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_encrypted_attachment_protection_enabled/gmail_encrypted_attachment_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailEncryptedAttachmentProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled import ( + gmail_encrypted_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_encrypted_attachment_protection=True, + encrypted_attachment_protection_consequence="QUARANTINE", + ) + + check = gmail_encrypted_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "QUARANTINE" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled import ( + gmail_encrypted_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_encrypted_attachment_protection=True, + encrypted_attachment_protection_consequence="NO_ACTION", + ) + + check = gmail_encrypted_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled import ( + gmail_encrypted_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_encrypted_attachment_protection=False, + encrypted_attachment_protection_consequence="WARNING", + ) + + check = gmail_encrypted_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_pass_using_default(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled import ( + gmail_encrypted_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_encrypted_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "secure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_encrypted_attachment_protection_enabled.gmail_encrypted_attachment_protection_enabled import ( + gmail_encrypted_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_encrypted_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled_test.py new file mode 100644 index 00000000000..704fc8d2bbb --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_groups_spoofing_protection_enabled/gmail_groups_spoofing_protection_enabled_test.py @@ -0,0 +1,187 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailGroupsSpoofingProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled import ( + gmail_groups_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_groups_spoofing=True, + groups_spoofing_consequence="SPAM_FOLDER", + ) + + check = gmail_groups_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "all groups" in findings[0].status_extended + assert "SPAM_FOLDER" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_pass_private_groups_only(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled import ( + gmail_groups_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_groups_spoofing=True, + groups_spoofing_visibility_type="PRIVATE_GROUPS_ONLY", + groups_spoofing_consequence="SPAM_FOLDER", + ) + + check = gmail_groups_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "private groups only" in findings[0].status_extended + assert "SPAM_FOLDER" in findings[0].status_extended + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled import ( + gmail_groups_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_groups_spoofing=True, + groups_spoofing_consequence="NO_ACTION", + ) + + check = gmail_groups_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled import ( + gmail_groups_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_groups_spoofing=False, + groups_spoofing_consequence="WARNING", + ) + + check = gmail_groups_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_fail_no_policy_set(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled import ( + gmail_groups_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_groups_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "insecure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_groups_spoofing_protection_enabled.gmail_groups_spoofing_protection_enabled import ( + gmail_groups_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_groups_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled_test.py new file mode 100644 index 00000000000..bae9d42b49c --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_inbound_domain_spoofing_protection_enabled/gmail_inbound_domain_spoofing_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailInboundDomainSpoofingProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled import ( + gmail_inbound_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_inbound_domain_spoofing=True, + inbound_domain_spoofing_consequence="QUARANTINE", + ) + + check = gmail_inbound_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "QUARANTINE" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled import ( + gmail_inbound_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_inbound_domain_spoofing=True, + inbound_domain_spoofing_consequence="NO_ACTION", + ) + + check = gmail_inbound_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled import ( + gmail_inbound_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_inbound_domain_spoofing=False, + inbound_domain_spoofing_consequence="WARNING", + ) + + check = gmail_inbound_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_pass_using_default(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled import ( + gmail_inbound_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_inbound_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "secure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_inbound_domain_spoofing_protection_enabled.gmail_inbound_domain_spoofing_protection_enabled import ( + gmail_inbound_domain_spoofing_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_inbound_domain_spoofing_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled_test.py new file mode 100644 index 00000000000..25333e195b5 --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_script_attachment_protection_enabled/gmail_script_attachment_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailScriptAttachmentProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled import ( + gmail_script_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_script_attachment_protection=True, + script_attachment_protection_consequence="QUARANTINE", + ) + + check = gmail_script_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "QUARANTINE" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled import ( + gmail_script_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_script_attachment_protection=True, + script_attachment_protection_consequence="NO_ACTION", + ) + + check = gmail_script_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled import ( + gmail_script_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + enable_script_attachment_protection=False, + script_attachment_protection_consequence="WARNING", + ) + + check = gmail_script_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_pass_using_default(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled import ( + gmail_script_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_script_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "secure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_script_attachment_protection_enabled.gmail_script_attachment_protection_enabled import ( + gmail_script_attachment_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_script_attachment_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_service_test.py b/tests/providers/googleworkspace/services/gmail/gmail_service_test.py index ca1c4c249f9..cdfa29ed143 100644 --- a/tests/providers/googleworkspace/services/gmail/gmail_service_test.py +++ b/tests/providers/googleworkspace/services/gmail/gmail_service_test.py @@ -34,8 +34,11 @@ def test_gmail_fetch_policies_all_settings(self): "setting": { "type": "settings/gmail.email_attachment_safety", "value": { + "enableEncryptedAttachmentProtection": True, "encryptedAttachmentProtectionConsequence": "SPAM_FOLDER", + "enableAttachmentWithScriptsProtection": True, "scriptAttachmentProtectionConsequence": "QUARANTINE", + "enableAnomalousAttachmentProtection": True, "anomalousAttachmentProtectionConsequence": "WARNING", }, } @@ -54,10 +57,15 @@ def test_gmail_fetch_policies_all_settings(self): "setting": { "type": "settings/gmail.spoofing_and_authentication", "value": { + "detectDomainNameSpoofing": True, "domainSpoofingConsequence": "SPAM_FOLDER", + "detectEmployeeNameSpoofing": True, "employeeNameSpoofingConsequence": "SPAM_FOLDER", + "detectDomainSpoofingFromUnauthenticatedSenders": True, "inboundDomainSpoofingConsequence": "QUARANTINE", + "detectUnauthenticatedEmails": True, "unauthenticatedEmailConsequence": "WARNING", + "detectGroupsSpoofing": True, "groupsSpoofingConsequence": "SPAM_FOLDER", }, } @@ -121,23 +129,31 @@ def test_gmail_fetch_policies_all_settings(self): assert gmail.policies_fetched is True assert gmail.policies.enable_mail_delegation is False + assert gmail.policies.enable_encrypted_attachment_protection is True assert ( gmail.policies.encrypted_attachment_protection_consequence == "SPAM_FOLDER" ) + assert gmail.policies.enable_script_attachment_protection is True assert ( gmail.policies.script_attachment_protection_consequence == "QUARANTINE" ) + assert gmail.policies.enable_anomalous_attachment_protection is True assert ( gmail.policies.anomalous_attachment_protection_consequence == "WARNING" ) assert gmail.policies.enable_shortener_scanning is True assert gmail.policies.enable_external_image_scanning is True assert gmail.policies.enable_aggressive_warnings_on_untrusted_links is True + assert gmail.policies.detect_domain_name_spoofing is True assert gmail.policies.domain_spoofing_consequence == "SPAM_FOLDER" + assert gmail.policies.detect_employee_name_spoofing is True assert gmail.policies.employee_name_spoofing_consequence == "SPAM_FOLDER" + assert gmail.policies.detect_inbound_domain_spoofing is True assert gmail.policies.inbound_domain_spoofing_consequence == "QUARANTINE" + assert gmail.policies.detect_unauthenticated_emails is True assert gmail.policies.unauthenticated_email_consequence == "WARNING" + assert gmail.policies.detect_groups_spoofing is True assert gmail.policies.groups_spoofing_consequence == "SPAM_FOLDER" assert gmail.policies.enable_pop_access is False assert gmail.policies.enable_imap_access is False @@ -464,16 +480,24 @@ def test_gmail_policies_model(self): policies = GmailPolicies( enable_mail_delegation=False, + enable_encrypted_attachment_protection=True, encrypted_attachment_protection_consequence="SPAM_FOLDER", + enable_script_attachment_protection=True, script_attachment_protection_consequence="QUARANTINE", + enable_anomalous_attachment_protection=True, anomalous_attachment_protection_consequence="WARNING", enable_shortener_scanning=True, enable_external_image_scanning=True, enable_aggressive_warnings_on_untrusted_links=True, + detect_domain_name_spoofing=True, domain_spoofing_consequence="SPAM_FOLDER", + detect_employee_name_spoofing=True, employee_name_spoofing_consequence="SPAM_FOLDER", + detect_inbound_domain_spoofing=True, inbound_domain_spoofing_consequence="QUARANTINE", + detect_unauthenticated_emails=True, unauthenticated_email_consequence="WARNING", + detect_groups_spoofing=True, groups_spoofing_consequence="SPAM_FOLDER", enable_pop_access=False, enable_imap_access=False, @@ -484,8 +508,10 @@ def test_gmail_policies_model(self): ) assert policies.enable_mail_delegation is False + assert policies.enable_encrypted_attachment_protection is True assert policies.encrypted_attachment_protection_consequence == "SPAM_FOLDER" assert policies.enable_shortener_scanning is True + assert policies.detect_domain_name_spoofing is True assert policies.domain_spoofing_consequence == "SPAM_FOLDER" assert policies.enable_pop_access is False assert policies.enable_auto_forwarding is False diff --git a/tests/providers/googleworkspace/services/gmail/gmail_shortener_scanning_enabled/__init__.py b/tests/providers/googleworkspace/services/gmail/gmail_shortener_scanning_enabled/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled_test.py new file mode 100644 index 00000000000..90d9beefcc9 --- /dev/null +++ b/tests/providers/googleworkspace/services/gmail/gmail_unauthenticated_email_protection_enabled/gmail_unauthenticated_email_protection_enabled_test.py @@ -0,0 +1,154 @@ +from unittest.mock import patch + +from prowler.providers.googleworkspace.services.gmail.gmail_service import GmailPolicies +from tests.providers.googleworkspace.googleworkspace_fixtures import ( + CUSTOMER_ID, + DOMAIN, + set_mocked_googleworkspace_provider, +) + + +class TestGmailUnauthenticatedEmailProtectionEnabled: + def test_pass(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled import ( + gmail_unauthenticated_email_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_unauthenticated_emails=True, + unauthenticated_email_consequence="WARNING", + ) + + check = gmail_unauthenticated_email_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "PASS" + assert "WARNING" in findings[0].status_extended + assert findings[0].resource_name == DOMAIN + assert findings[0].customer_id == CUSTOMER_ID + + def test_fail_no_action(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled import ( + gmail_unauthenticated_email_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_unauthenticated_emails=True, + unauthenticated_email_consequence="NO_ACTION", + ) + + check = gmail_unauthenticated_email_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "no action" in findings[0].status_extended + + def test_fail_protection_disabled(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled import ( + gmail_unauthenticated_email_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies( + detect_unauthenticated_emails=False, + unauthenticated_email_consequence="WARNING", + ) + + check = gmail_unauthenticated_email_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "disabled" in findings[0].status_extended + + def test_fail_no_policy_set(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled import ( + gmail_unauthenticated_email_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = True + mock_client.policies = GmailPolicies() + + check = gmail_unauthenticated_email_protection_enabled() + findings = check.execute() + + assert len(findings) == 1 + assert findings[0].status == "FAIL" + assert "insecure default" in findings[0].status_extended + + def test_no_findings_when_fetch_failed(self): + mock_provider = set_mocked_googleworkspace_provider() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled.gmail_client" + ) as mock_client, + ): + from prowler.providers.googleworkspace.services.gmail.gmail_unauthenticated_email_protection_enabled.gmail_unauthenticated_email_protection_enabled import ( + gmail_unauthenticated_email_protection_enabled, + ) + + mock_client.provider = mock_provider + mock_client.policies_fetched = False + mock_client.policies = GmailPolicies() + + check = gmail_unauthenticated_email_protection_enabled() + findings = check.execute() + + assert len(findings) == 0 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/__init__.py b/tests/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled_test.py b/tests/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled_test.py index 611848b12fc..9146f699c2f 100644 --- a/tests/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled_test.py +++ b/tests/providers/googleworkspace/services/gmail/gmail_untrusted_link_warnings_enabled/gmail_untrusted_link_warnings_enabled_test.py @@ -69,7 +69,7 @@ def test_fail_disabled(self): assert findings[0].status == "FAIL" assert "disabled" in findings[0].status_extended - def test_pass_using_default(self): + def test_fail_insecure_default(self): mock_provider = set_mocked_googleworkspace_provider() with ( @@ -95,8 +95,8 @@ def test_pass_using_default(self): findings = check.execute() assert len(findings) == 1 - assert findings[0].status == "PASS" - assert "secure default" in findings[0].status_extended + assert findings[0].status == "FAIL" + assert "insecure default" in findings[0].status_extended def test_no_findings_when_fetch_failed(self): mock_provider = set_mocked_googleworkspace_provider()