From 5ee1e0a9eb46230e2d076c0c42138ef26b47eeb0 Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Tue, 27 Feb 2024 18:05:21 +0100 Subject: [PATCH] feat(gcp): add 3 new checks for GKE CIS (#3440) --- .../__init__.py | 0 ...s_container_analysis_enabled.metadata.json | 33 +++ .../artifacts_container_analysis_enabled.py | 31 +++ .../__init__.py | 0 ...r_container_scanning_enabled.metadata.json | 33 +++ .../gcr_container_scanning_enabled.py | 31 +++ .../providers/gcp/services/gke/__init__.py | 0 .../providers/gcp/services/gke/gke_client.py | 4 + .../__init__.py | 0 ...r_no_default_service_account.metadata.json | 33 +++ .../gke_cluster_no_default_service_account.py | 26 +++ .../providers/gcp/services/gke/gke_service.py | 90 ++++++++ .../__init__.py | 0 ...oud_asset_inventory_enabled.metadata.json} | 6 +- .../iam_cloud_asset_inventory_enabled.py} | 2 +- tests/providers/gcp/lib/audit_info_utils.py | 1 + ...pikeys_api_restrictions_configured_test.py | 2 +- .../apikeys_key_exists_test.py | 2 +- .../apikeys_key_rotated_in_90_days_test.py | 2 +- ...tifacts_container_analysis_enabled_test.py | 68 ++++++ .../bigquery_dataset_public_access_test.py | 2 +- ...ock_project_wide_ssh_keys_disabled_test.py | 2 +- ...ute_default_service_account_in_use_test.py | 2 +- ...ccount_in_use_with_full_api_access_test.py | 2 +- ...e_encryption_with_csek_is_disabled_test.py | 2 +- ...nce_confidential_computing_enabled_test.py | 2 +- .../compute_ip_forwarding_is_enabled_test.py | 2 +- ...mpute_loadbalancer_logging_enabled_test.py | 2 +- ...ompute_network_dns_logging_enabled_test.py | 3 +- .../compute_network_not_legacy_test.py | 2 +- .../compute_project_os_login_enabled_test.py | 2 +- ...p_access_from_the_internet_allowed_test.py | 2 +- .../compute_serial_ports_in_use_test.py | 2 +- .../compute_shielded_vm_enabled_test.py | 2 +- ...h_access_from_the_internet_allowed_test.py | 2 +- .../compute_subnet_flow_logs_enabled_test.py | 2 +- ...aproc_encrypted_with_cmks_disabled_test.py | 2 +- .../dns_dnssec_disabled_test.py | 2 +- ...asha1_in_use_to_key_sign_in_dnssec_test.py | 2 +- ...sha1_in_use_to_zone_sign_in_dnssec_test.py | 2 +- .../gcr_container_scanning_enabled_test.py | 68 ++++++ ...cluster_no_default_service_account_test.py | 196 ++++++++++++++++++ ...am_account_access_approval_enabled_test.py | 3 +- .../iam_audit_logs_enabled_test.py | 2 +- ...iam_cloud_asset_inventory_enabled_test.py} | 31 ++- ..._no_service_roles_at_project_level_test.py | 2 +- ...tion_essential_contacts_configured_test.py | 2 - ...e_kms_enforce_separation_of_duties_test.py | 2 +- ...le_sa_enforce_separation_of_duties_test.py | 2 +- 49 files changed, 661 insertions(+), 52 deletions(-) rename prowler/providers/gcp/services/{serviceusage/serviceusage_cloudasset_inventory_enabled => artifacts/artifacts_container_analysis_enabled}/__init__.py (100%) create mode 100644 prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json create mode 100644 prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.py create mode 100644 prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/__init__.py create mode 100644 prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.metadata.json create mode 100644 prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.py create mode 100644 prowler/providers/gcp/services/gke/__init__.py create mode 100644 prowler/providers/gcp/services/gke/gke_client.py create mode 100644 prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/__init__.py create mode 100644 prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.metadata.json create mode 100644 prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.py create mode 100644 prowler/providers/gcp/services/gke/gke_service.py create mode 100644 prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/__init__.py rename prowler/providers/gcp/services/{serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.metadata.json => iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.metadata.json} (93%) rename prowler/providers/gcp/services/{serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.py => iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.py} (95%) create mode 100644 tests/providers/gcp/lib/audit_info_utils.py create mode 100644 tests/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled_test.py create mode 100644 tests/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled_test.py create mode 100644 tests/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account_test.py rename tests/providers/gcp/services/{serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled_test.py => iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled_test.py} (59%) diff --git a/prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/__init__.py b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/__init__.py similarity index 100% rename from prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/__init__.py rename to prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/__init__.py diff --git a/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json new file mode 100644 index 00000000..7aafa5eb --- /dev/null +++ b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json @@ -0,0 +1,33 @@ +{ + "Provider": "gcp", + "CheckID": "artifacts_container_analysis_enabled", + "CheckTitle": "Ensure Image Vulnerability Analysis using AR Container Analysis or a third-party provider", + "CheckType": [ + "Security", + "Configuration" + ], + "ServiceName": "Artifact Registry", + "SubServiceName": "Container Analysis", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Service", + "Description": "Scan images stored in Google Container Registry (GCR) for vulnerabilities using AR Container Analysis or a third-party provider. This helps identify and mitigate security risks associated with known vulnerabilities in container images.", + "Risk": "Without image vulnerability scanning, container images stored in Artifact Registry may contain known vulnerabilities, increasing the risk of exploitation by malicious actors.", + "RelatedUrl": "https://cloud.google.com/artifact-analysis/docs", + "Remediation": { + "Code": { + "CLI": "gcloud services enable containeranalysis.googleapis.com", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable vulnerability scanning for images stored in Artifact Registry using AR Container Analysis or a third-party provider.", + "Url": "https://cloud.google.com/artifact-analysis/docs/container-scanning-overview" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "By default, AR Container Analysis is disabled." +} diff --git a/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.py b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.py new file mode 100644 index 00000000..5c601819 --- /dev/null +++ b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.py @@ -0,0 +1,31 @@ +from prowler.lib.check.models import Check, Check_Report_GCP +from prowler.providers.gcp.services.serviceusage.serviceusage_client import ( + serviceusage_client, +) + + +class artifacts_container_analysis_enabled(Check): + def execute(self) -> Check_Report_GCP: + findings = [] + for project_id in serviceusage_client.project_ids: + report = Check_Report_GCP(self.metadata()) + report.project_id = project_id + report.resource_id = "containeranalysis.googleapis.com" + report.resource_name = "AR Container Analysis" + report.location = serviceusage_client.region + report.status = "FAIL" + report.status_extended = ( + f"AR Container Analysis is not enabled in project {project_id}." + ) + for active_service in serviceusage_client.active_services.get( + project_id, [] + ): + if active_service.name == "containeranalysis.googleapis.com": + report.status = "PASS" + report.status_extended = ( + f"AR Container Analysis is enabled in project {project_id}." + ) + break + findings.append(report) + + return findings diff --git a/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/__init__.py b/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.metadata.json b/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.metadata.json new file mode 100644 index 00000000..0820c111 --- /dev/null +++ b/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.metadata.json @@ -0,0 +1,33 @@ +{ + "Provider": "gcp", + "CheckID": "gcr_container_scanning_enabled", + "CheckTitle": "Ensure Image Vulnerability Scanning using GCR Container Scanning or a third-party provider", + "CheckType": [ + "Security", + "Configuration" + ], + "ServiceName": "Google Container Registry (GCR)", + "SubServiceName": "Container Scanning", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Service", + "Description": "Scan images stored in Google Container Registry (GCR) for vulnerabilities using GCR Container Scanning or a third-party provider. This helps identify and mitigate security risks associated with known vulnerabilities in container images.", + "Risk": "Without image vulnerability scanning, container images stored in GCR may contain known vulnerabilities, increasing the risk of exploitation by malicious actors.", + "RelatedUrl": "https://cloud.google.com/container-registry/docs/container-analysis", + "Remediation": { + "Code": { + "CLI": "gcloud services enable containerscanning.googleapis.com", + "NativeIaC": "", + "Other": "", + "Terraform": "https://docs.bridgecrew.io/docs/ensure-gcp-gcr-container-vulnerability-scanning-is-enabled#terraform" + }, + "Recommendation": { + "Text": "Enable vulnerability scanning for images stored in GCR using GCR Container Scanning or a third-party provider.", + "Url": "https://cloud.google.com/container-registry/docs/container-best-practices" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "By default, GCR Container Scanning is disabled." +} diff --git a/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.py b/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.py new file mode 100644 index 00000000..87097e51 --- /dev/null +++ b/prowler/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled.py @@ -0,0 +1,31 @@ +from prowler.lib.check.models import Check, Check_Report_GCP +from prowler.providers.gcp.services.serviceusage.serviceusage_client import ( + serviceusage_client, +) + + +class gcr_container_scanning_enabled(Check): + def execute(self) -> Check_Report_GCP: + findings = [] + for project_id in serviceusage_client.project_ids: + report = Check_Report_GCP(self.metadata()) + report.project_id = project_id + report.resource_id = "containerscanning.googleapis.com" + report.resource_name = "GCR Container Scanning" + report.location = serviceusage_client.region + report.status = "FAIL" + report.status_extended = ( + f"GCR Container Scanning is not enabled in project {project_id}." + ) + for active_service in serviceusage_client.active_services.get( + project_id, [] + ): + if active_service.name == "containerscanning.googleapis.com": + report.status = "PASS" + report.status_extended = ( + f"GCR Container Scanning is enabled in project {project_id}." + ) + break + findings.append(report) + + return findings diff --git a/prowler/providers/gcp/services/gke/__init__.py b/prowler/providers/gcp/services/gke/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/gcp/services/gke/gke_client.py b/prowler/providers/gcp/services/gke/gke_client.py new file mode 100644 index 00000000..7b165a2c --- /dev/null +++ b/prowler/providers/gcp/services/gke/gke_client.py @@ -0,0 +1,4 @@ +from prowler.providers.gcp.lib.audit_info.audit_info import gcp_audit_info +from prowler.providers.gcp.services.gke.gke_service import GKE + +gke_client = GKE(gcp_audit_info) diff --git a/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/__init__.py b/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.metadata.json b/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.metadata.json new file mode 100644 index 00000000..672f99e5 --- /dev/null +++ b/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.metadata.json @@ -0,0 +1,33 @@ +{ + "Provider": "gcp", + "CheckID": "gke_cluster_no_default_service_account", + "CheckTitle": "Ensure GKE clusters are not running using the Compute Engine default service account", + "CheckType": [ + "Security", + "Configuration" + ], + "ServiceName": "Google Kubernetes Engine (GKE)", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Service", + "Description": "Ensure GKE clusters are not running using the Compute Engine default service account. Create and use minimally privileged service accounts for GKE cluster nodes instead of using the Compute Engine default service account to minimize unnecessary permissions.", + "Risk": "Using the Compute Engine default service account for GKE cluster nodes may grant excessive permissions, increasing the risk of unauthorized access or compromise if a node is compromised.", + "RelatedUrl": "https://cloud.google.com/compute/docs/access/service-accounts#default_service_account", + "Remediation": { + "Code": { + "CLI": "gcloud container node-pools create [NODE_POOL] --service-account=[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com --cluster=[CLUSTER_NAME] --zone [COMPUTE_ZONE]", + "NativeIaC": "", + "Other": "", + "Terraform": "https://docs.bridgecrew.io/docs/ensure-gke-clusters-are-not-running-using-the-compute-engine-default-service-account#terraform" + }, + "Recommendation": { + "Text": "Create and use minimally privileged service accounts for GKE cluster nodes instead of using the Compute Engine default service account.", + "Url": "https://cloud.google.com/compute/docs/access/service-accounts#default_service_account" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "By default, nodes use the Compute Engine default service account when you create a new cluster." +} diff --git a/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.py b/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.py new file mode 100644 index 00000000..e412d181 --- /dev/null +++ b/prowler/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account.py @@ -0,0 +1,26 @@ +from prowler.lib.check.models import Check, Check_Report_GCP +from prowler.providers.gcp.services.gke.gke_client import gke_client + + +class gke_cluster_no_default_service_account(Check): + def execute(self) -> Check_Report_GCP: + findings = [] + for cluster in gke_client.clusters.values(): + report = Check_Report_GCP(self.metadata()) + report.project_id = cluster.project_id + report.resource_id = cluster.id + report.resource_name = cluster.name + report.location = cluster.location + report.status = "PASS" + report.status_extended = f"GKE cluster {cluster.name} is not using the Compute Engine default service account." + if not cluster.node_pools and cluster.service_account == "default": + report.status = "FAIL" + report.status_extended = f"GKE cluster {cluster.name} is using the Compute Engine default service account." + for node_pool in cluster.node_pools: + if node_pool.service_account == "default": + report.status = "FAIL" + report.status_extended = f"GKE cluster {cluster.name} is using the Compute Engine default service account." + break + findings.append(report) + + return findings diff --git a/prowler/providers/gcp/services/gke/gke_service.py b/prowler/providers/gcp/services/gke/gke_service.py new file mode 100644 index 00000000..e657e3d6 --- /dev/null +++ b/prowler/providers/gcp/services/gke/gke_service.py @@ -0,0 +1,90 @@ +from pydantic import BaseModel + +from prowler.lib.logger import logger +from prowler.providers.gcp.lib.service.service import GCPService + + +################## GKE +class GKE(GCPService): + def __init__(self, audit_info): + super().__init__("container", audit_info, api_version="v1beta1") + self.locations = [] + self.__get_locations__() + self.clusters = {} + self.__threading_call__(self.__get_clusters__, self.locations) + + def __get_locations__(self): + for project_id in self.project_ids: + try: + request = ( + self.client.projects() + .locations() + .list(parent="projects/" + project_id) + ) + response = request.execute() + + for location in response["locations"]: + self.locations.append( + Location(name=location["name"], project_id=project_id) + ) + + except Exception as error: + logger.error( + f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + def __get_clusters__(self, location): + try: + request = ( + self.client.projects() + .locations() + .clusters() + .list( + parent=f"projects/{location.project_id}/locations/{location.name}" + ) + ) + response = request.execute(http=self.__get_AuthorizedHttp_client__()) + for cluster in response.get("clusters", []): + node_pools = [] + for node_pool in cluster["nodePools"]: + node_pools.append( + NodePool( + name=node_pool["name"], + locations=node_pool["locations"], + service_account=node_pool["config"]["serviceAccount"], + project_id=location.project_id, + ) + ) + self.clusters[cluster["id"]] = Cluster( + name=cluster["name"], + id=cluster["id"], + location=cluster["location"], + service_account=cluster["nodeConfig"]["serviceAccount"], + node_pools=node_pools, + project_id=location.project_id, + ) + except Exception as error: + logger.error( + f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + +class Location(BaseModel): + name: str + project_id: str + + +class NodePool(BaseModel): + name: str + locations: list + service_account: str + project_id: str + + +class Cluster(BaseModel): + name: str + id: str + location: str + service_account: str + node_pools: list[NodePool] + project_id: str diff --git a/prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/__init__.py b/prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.metadata.json b/prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.metadata.json similarity index 93% rename from prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.metadata.json rename to prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.metadata.json index 2eef4104..49441be9 100644 --- a/prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.metadata.json +++ b/prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.metadata.json @@ -1,10 +1,10 @@ { "Provider": "gcp", - "CheckID": "serviceusage_cloudasset_inventory_enabled", + "CheckID": "iam_cloud_asset_inventory_enabled", "CheckTitle": "Ensure Cloud Asset Inventory Is Enabled", "CheckType": [], - "ServiceName": "serviceusage", - "SubServiceName": "", + "ServiceName": "iam", + "SubServiceName": "Asset Inventory", "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "Service", diff --git a/prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.py b/prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.py similarity index 95% rename from prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.py rename to prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.py index 94eaab27..8803f7cf 100644 --- a/prowler/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled.py +++ b/prowler/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled.py @@ -4,7 +4,7 @@ from prowler.providers.gcp.services.serviceusage.serviceusage_client import ( ) -class serviceusage_cloudasset_inventory_enabled(Check): +class iam_cloud_asset_inventory_enabled(Check): def execute(self) -> Check_Report_GCP: findings = [] for project_id in serviceusage_client.project_ids: diff --git a/tests/providers/gcp/lib/audit_info_utils.py b/tests/providers/gcp/lib/audit_info_utils.py new file mode 100644 index 00000000..60a900cd --- /dev/null +++ b/tests/providers/gcp/lib/audit_info_utils.py @@ -0,0 +1 @@ +GCP_PROJECT_ID = "123456789012" diff --git a/tests/providers/gcp/services/apikeys/apikeys_api_restrictions_configured/apikeys_api_restrictions_configured_test.py b/tests/providers/gcp/services/apikeys/apikeys_api_restrictions_configured/apikeys_api_restrictions_configured_test.py index c1145ec0..45cca513 100644 --- a/tests/providers/gcp/services/apikeys/apikeys_api_restrictions_configured/apikeys_api_restrictions_configured_test.py +++ b/tests/providers/gcp/services/apikeys/apikeys_api_restrictions_configured/apikeys_api_restrictions_configured_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_apikeys_api_restrictions_configured: diff --git a/tests/providers/gcp/services/apikeys/apikeys_key_exists/apikeys_key_exists_test.py b/tests/providers/gcp/services/apikeys/apikeys_key_exists/apikeys_key_exists_test.py index 9160caf7..b6449c99 100644 --- a/tests/providers/gcp/services/apikeys/apikeys_key_exists/apikeys_key_exists_test.py +++ b/tests/providers/gcp/services/apikeys/apikeys_key_exists/apikeys_key_exists_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_apikeys_key_exists: diff --git a/tests/providers/gcp/services/apikeys/apikeys_key_rotated_in_90_days/apikeys_key_rotated_in_90_days_test.py b/tests/providers/gcp/services/apikeys/apikeys_key_rotated_in_90_days/apikeys_key_rotated_in_90_days_test.py index 82267bd1..e531c00e 100644 --- a/tests/providers/gcp/services/apikeys/apikeys_key_rotated_in_90_days/apikeys_key_rotated_in_90_days_test.py +++ b/tests/providers/gcp/services/apikeys/apikeys_key_rotated_in_90_days/apikeys_key_rotated_in_90_days_test.py @@ -2,7 +2,7 @@ from datetime import datetime, timedelta, timezone from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_apikeys_key_rotated_in_90_days: diff --git a/tests/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled_test.py b/tests/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled_test.py new file mode 100644 index 00000000..92d4b941 --- /dev/null +++ b/tests/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled_test.py @@ -0,0 +1,68 @@ +from unittest import mock + +from prowler.providers.gcp.services.serviceusage.serviceusage_service import Service +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID + + +class Test_artifacts_container_analysis_enabled: + def test_serviceusage_no_active_services(self): + serviceusage_client = mock.MagicMock + serviceusage_client.active_services = {} + serviceusage_client.project_ids = [GCP_PROJECT_ID] + serviceusage_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.artifacts.artifacts_container_analysis_enabled.artifacts_container_analysis_enabled.serviceusage_client", + new=serviceusage_client, + ): + from prowler.providers.gcp.services.artifacts.artifacts_container_analysis_enabled.artifacts_container_analysis_enabled import ( + artifacts_container_analysis_enabled, + ) + + check = artifacts_container_analysis_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"AR Container Analysis is not enabled in project {GCP_PROJECT_ID}." + ) + assert result[0].resource_id == "containeranalysis.googleapis.com" + assert result[0].project_id == GCP_PROJECT_ID + assert result[0].resource_name == "AR Container Analysis" + assert result[0].location == serviceusage_client.region + + def test_serviceusage_active_cloudasset(self): + serviceusage_client = mock.MagicMock + serviceusage_client.active_services = { + GCP_PROJECT_ID: [ + Service( + name="containeranalysis.googleapis.com", + title="AR Container Analysis", + project_id=GCP_PROJECT_ID, + ) + ] + } + serviceusage_client.project_ids = [GCP_PROJECT_ID] + serviceusage_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.artifacts.artifacts_container_analysis_enabled.artifacts_container_analysis_enabled.serviceusage_client", + new=serviceusage_client, + ): + from prowler.providers.gcp.services.artifacts.artifacts_container_analysis_enabled.artifacts_container_analysis_enabled import ( + artifacts_container_analysis_enabled, + ) + + check = artifacts_container_analysis_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"AR Container Analysis is enabled in project {GCP_PROJECT_ID}." + ) + assert result[0].resource_id == "containeranalysis.googleapis.com" + assert result[0].project_id == GCP_PROJECT_ID + assert result[0].resource_name == "AR Container Analysis" + assert result[0].location == serviceusage_client.region diff --git a/tests/providers/gcp/services/bigquery/bigquery_dataset_public_access/bigquery_dataset_public_access_test.py b/tests/providers/gcp/services/bigquery/bigquery_dataset_public_access/bigquery_dataset_public_access_test.py index 75275129..b4a59292 100644 --- a/tests/providers/gcp/services/bigquery/bigquery_dataset_public_access/bigquery_dataset_public_access_test.py +++ b/tests/providers/gcp/services/bigquery/bigquery_dataset_public_access/bigquery_dataset_public_access_test.py @@ -1,6 +1,6 @@ from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_bigquery_dataset_public_access: diff --git a/tests/providers/gcp/services/compute/compute_block_project_wide_ssh_keys_disabled/compute_block_project_wide_ssh_keys_disabled_test.py b/tests/providers/gcp/services/compute/compute_block_project_wide_ssh_keys_disabled/compute_block_project_wide_ssh_keys_disabled_test.py index 8b699187..a7556b6e 100644 --- a/tests/providers/gcp/services/compute/compute_block_project_wide_ssh_keys_disabled/compute_block_project_wide_ssh_keys_disabled_test.py +++ b/tests/providers/gcp/services/compute/compute_block_project_wide_ssh_keys_disabled/compute_block_project_wide_ssh_keys_disabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_block_project_wide_ssh_keys_disabled: diff --git a/tests/providers/gcp/services/compute/compute_default_service_account_in_use/compute_default_service_account_in_use_test.py b/tests/providers/gcp/services/compute/compute_default_service_account_in_use/compute_default_service_account_in_use_test.py index 2e63b975..8a70974a 100644 --- a/tests/providers/gcp/services/compute/compute_default_service_account_in_use/compute_default_service_account_in_use_test.py +++ b/tests/providers/gcp/services/compute/compute_default_service_account_in_use/compute_default_service_account_in_use_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_default_service_account_in_use: diff --git a/tests/providers/gcp/services/compute/compute_default_service_account_in_use_with_full_api_access/compute_default_service_account_in_use_with_full_api_access_test.py b/tests/providers/gcp/services/compute/compute_default_service_account_in_use_with_full_api_access/compute_default_service_account_in_use_with_full_api_access_test.py index d3158090..85048c06 100644 --- a/tests/providers/gcp/services/compute/compute_default_service_account_in_use_with_full_api_access/compute_default_service_account_in_use_with_full_api_access_test.py +++ b/tests/providers/gcp/services/compute/compute_default_service_account_in_use_with_full_api_access/compute_default_service_account_in_use_with_full_api_access_test.py @@ -1,6 +1,6 @@ from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_default_service_account_in_use_with_full_api_access: diff --git a/tests/providers/gcp/services/compute/compute_encryption_with_csek_is_disabled/compute_encryption_with_csek_is_disabled_test.py b/tests/providers/gcp/services/compute/compute_encryption_with_csek_is_disabled/compute_encryption_with_csek_is_disabled_test.py index 4d24f2d7..56914fd1 100644 --- a/tests/providers/gcp/services/compute/compute_encryption_with_csek_is_disabled/compute_encryption_with_csek_is_disabled_test.py +++ b/tests/providers/gcp/services/compute/compute_encryption_with_csek_is_disabled/compute_encryption_with_csek_is_disabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_encryption_with_csek_enabled: diff --git a/tests/providers/gcp/services/compute/compute_instance_confidential_computing_enabled/compute_instance_confidential_computing_enabled_test.py b/tests/providers/gcp/services/compute/compute_instance_confidential_computing_enabled/compute_instance_confidential_computing_enabled_test.py index a64284b9..b750378e 100644 --- a/tests/providers/gcp/services/compute/compute_instance_confidential_computing_enabled/compute_instance_confidential_computing_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_instance_confidential_computing_enabled/compute_instance_confidential_computing_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_confidential_computing_enabled: diff --git a/tests/providers/gcp/services/compute/compute_ip_forwarding_is_enabled/compute_ip_forwarding_is_enabled_test.py b/tests/providers/gcp/services/compute/compute_ip_forwarding_is_enabled/compute_ip_forwarding_is_enabled_test.py index 53740aeb..2eb604f0 100644 --- a/tests/providers/gcp/services/compute/compute_ip_forwarding_is_enabled/compute_ip_forwarding_is_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_ip_forwarding_is_enabled/compute_ip_forwarding_is_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_ip_forwarding_is_enabled: diff --git a/tests/providers/gcp/services/compute/compute_loadbalancer_logging_enabled/compute_loadbalancer_logging_enabled_test.py b/tests/providers/gcp/services/compute/compute_loadbalancer_logging_enabled/compute_loadbalancer_logging_enabled_test.py index 48cf8956..a2c6d8c4 100644 --- a/tests/providers/gcp/services/compute/compute_loadbalancer_logging_enabled/compute_loadbalancer_logging_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_loadbalancer_logging_enabled/compute_loadbalancer_logging_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_loadbalancer_logging_enabled: diff --git a/tests/providers/gcp/services/compute/compute_network_dns_logging_enabled/compute_network_dns_logging_enabled_test.py b/tests/providers/gcp/services/compute/compute_network_dns_logging_enabled/compute_network_dns_logging_enabled_test.py index 8e1ff2fb..67e62eee 100644 --- a/tests/providers/gcp/services/compute/compute_network_dns_logging_enabled/compute_network_dns_logging_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_network_dns_logging_enabled/compute_network_dns_logging_enabled_test.py @@ -2,8 +2,7 @@ from re import search from unittest import mock from prowler.providers.gcp.services.dns.dns_service import Policy - -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_network_dns_logging_enabled: diff --git a/tests/providers/gcp/services/compute/compute_network_not_legacy/compute_network_not_legacy_test.py b/tests/providers/gcp/services/compute/compute_network_not_legacy/compute_network_not_legacy_test.py index 234b8315..dfcbeb2b 100644 --- a/tests/providers/gcp/services/compute/compute_network_not_legacy/compute_network_not_legacy_test.py +++ b/tests/providers/gcp/services/compute/compute_network_not_legacy/compute_network_not_legacy_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_network_not_legacy: diff --git a/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py b/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py index 6512a9c4..116cc738 100644 --- a/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_project_os_login_enabled: diff --git a/tests/providers/gcp/services/compute/compute_rdp_access_from_the_internet_allowed/compute_rdp_access_from_the_internet_allowed_test.py b/tests/providers/gcp/services/compute/compute_rdp_access_from_the_internet_allowed/compute_rdp_access_from_the_internet_allowed_test.py index 50d9225f..85d599a2 100644 --- a/tests/providers/gcp/services/compute/compute_rdp_access_from_the_internet_allowed/compute_rdp_access_from_the_internet_allowed_test.py +++ b/tests/providers/gcp/services/compute/compute_rdp_access_from_the_internet_allowed/compute_rdp_access_from_the_internet_allowed_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_firewall_rdp_access_from_the_internet_allowed: diff --git a/tests/providers/gcp/services/compute/compute_serial_ports_in_use/compute_serial_ports_in_use_test.py b/tests/providers/gcp/services/compute/compute_serial_ports_in_use/compute_serial_ports_in_use_test.py index 10ac1446..49e4f051 100644 --- a/tests/providers/gcp/services/compute/compute_serial_ports_in_use/compute_serial_ports_in_use_test.py +++ b/tests/providers/gcp/services/compute/compute_serial_ports_in_use/compute_serial_ports_in_use_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_serial_ports_in_use: diff --git a/tests/providers/gcp/services/compute/compute_shielded_vm_enabled/compute_shielded_vm_enabled_test.py b/tests/providers/gcp/services/compute/compute_shielded_vm_enabled/compute_shielded_vm_enabled_test.py index 7e134ecf..6e8ace82 100644 --- a/tests/providers/gcp/services/compute/compute_shielded_vm_enabled/compute_shielded_vm_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_shielded_vm_enabled/compute_shielded_vm_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_instance_shielded_vm_enabled: diff --git a/tests/providers/gcp/services/compute/compute_ssh_access_from_the_internet_allowed/compute_ssh_access_from_the_internet_allowed_test.py b/tests/providers/gcp/services/compute/compute_ssh_access_from_the_internet_allowed/compute_ssh_access_from_the_internet_allowed_test.py index 892ae55f..482d24d3 100644 --- a/tests/providers/gcp/services/compute/compute_ssh_access_from_the_internet_allowed/compute_ssh_access_from_the_internet_allowed_test.py +++ b/tests/providers/gcp/services/compute/compute_ssh_access_from_the_internet_allowed/compute_ssh_access_from_the_internet_allowed_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_firewall_ssh_access_from_the_internet_allowed: diff --git a/tests/providers/gcp/services/compute/compute_subnet_flow_logs_enabled/compute_subnet_flow_logs_enabled_test.py b/tests/providers/gcp/services/compute/compute_subnet_flow_logs_enabled/compute_subnet_flow_logs_enabled_test.py index 3f51e02d..ca8a9b0a 100644 --- a/tests/providers/gcp/services/compute/compute_subnet_flow_logs_enabled/compute_subnet_flow_logs_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_subnet_flow_logs_enabled/compute_subnet_flow_logs_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_compute_subnet_flow_logs_enabled: diff --git a/tests/providers/gcp/services/dataproc/dataproc_encrypted_with_cmks_disabled/dataproc_encrypted_with_cmks_disabled_test.py b/tests/providers/gcp/services/dataproc/dataproc_encrypted_with_cmks_disabled/dataproc_encrypted_with_cmks_disabled_test.py index a0b949a0..cf2190c3 100644 --- a/tests/providers/gcp/services/dataproc/dataproc_encrypted_with_cmks_disabled/dataproc_encrypted_with_cmks_disabled_test.py +++ b/tests/providers/gcp/services/dataproc/dataproc_encrypted_with_cmks_disabled/dataproc_encrypted_with_cmks_disabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_dataproc_encrypted_with_cmks_disabled: diff --git a/tests/providers/gcp/services/dns/dns_dnssec_disabled/dns_dnssec_disabled_test.py b/tests/providers/gcp/services/dns/dns_dnssec_disabled/dns_dnssec_disabled_test.py index 9da61495..d0f59413 100644 --- a/tests/providers/gcp/services/dns/dns_dnssec_disabled/dns_dnssec_disabled_test.py +++ b/tests/providers/gcp/services/dns/dns_dnssec_disabled/dns_dnssec_disabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_dns_dnssec_disabled: diff --git a/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_key_sign_in_dnssec/dns_rsasha1_in_use_to_key_sign_in_dnssec_test.py b/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_key_sign_in_dnssec/dns_rsasha1_in_use_to_key_sign_in_dnssec_test.py index 704f5a68..0ca8f39a 100644 --- a/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_key_sign_in_dnssec/dns_rsasha1_in_use_to_key_sign_in_dnssec_test.py +++ b/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_key_sign_in_dnssec/dns_rsasha1_in_use_to_key_sign_in_dnssec_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_dns_rsasha1_in_use_to_key_sign_in_dnssec: diff --git a/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_zone_sign_in_dnssec/dns_rsasha1_in_use_to_zone_sign_in_dnssec_test.py b/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_zone_sign_in_dnssec/dns_rsasha1_in_use_to_zone_sign_in_dnssec_test.py index e60e2866..638017b3 100644 --- a/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_zone_sign_in_dnssec/dns_rsasha1_in_use_to_zone_sign_in_dnssec_test.py +++ b/tests/providers/gcp/services/dns/dns_rsasha1_in_use_to_zone_sign_in_dnssec/dns_rsasha1_in_use_to_zone_sign_in_dnssec_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_dns_rsasha1_in_use_to_zone_sign_in_dnssec: diff --git a/tests/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled_test.py b/tests/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled_test.py new file mode 100644 index 00000000..da28d67e --- /dev/null +++ b/tests/providers/gcp/services/gcr/gcr_container_scanning_enabled/gcr_container_scanning_enabled_test.py @@ -0,0 +1,68 @@ +from unittest import mock + +from prowler.providers.gcp.services.serviceusage.serviceusage_service import Service +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID + + +class Test_gcr_container_scanning_enabled: + def test_serviceusage_no_active_services(self): + serviceusage_client = mock.MagicMock + serviceusage_client.active_services = {} + serviceusage_client.project_ids = [GCP_PROJECT_ID] + serviceusage_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.gcr.gcr_container_scanning_enabled.gcr_container_scanning_enabled.serviceusage_client", + new=serviceusage_client, + ): + from prowler.providers.gcp.services.gcr.gcr_container_scanning_enabled.gcr_container_scanning_enabled import ( + gcr_container_scanning_enabled, + ) + + check = gcr_container_scanning_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"GCR Container Scanning is not enabled in project {GCP_PROJECT_ID}." + ) + assert result[0].resource_id == "containerscanning.googleapis.com" + assert result[0].project_id == GCP_PROJECT_ID + assert result[0].resource_name == "GCR Container Scanning" + assert result[0].location == serviceusage_client.region + + def test_serviceusage_active_cloudasset(self): + serviceusage_client = mock.MagicMock + serviceusage_client.active_services = { + GCP_PROJECT_ID: [ + Service( + name="containerscanning.googleapis.com", + title="GCR Container Scanning", + project_id=GCP_PROJECT_ID, + ) + ] + } + serviceusage_client.project_ids = [GCP_PROJECT_ID] + serviceusage_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.gcr.gcr_container_scanning_enabled.gcr_container_scanning_enabled.serviceusage_client", + new=serviceusage_client, + ): + from prowler.providers.gcp.services.gcr.gcr_container_scanning_enabled.gcr_container_scanning_enabled import ( + gcr_container_scanning_enabled, + ) + + check = gcr_container_scanning_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"GCR Container Scanning is enabled in project {GCP_PROJECT_ID}." + ) + assert result[0].resource_id == "containerscanning.googleapis.com" + assert result[0].project_id == GCP_PROJECT_ID + assert result[0].resource_name == "GCR Container Scanning" + assert result[0].location == serviceusage_client.region diff --git a/tests/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account_test.py b/tests/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account_test.py new file mode 100644 index 00000000..68f1c68f --- /dev/null +++ b/tests/providers/gcp/services/gke/gke_cluster_no_default_service_account/gke_cluster_no_default_service_account_test.py @@ -0,0 +1,196 @@ +from unittest import mock + +from prowler.providers.gcp.services.gke.gke_service import Cluster, NodePool +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID + + +class Test_gke_cluster_no_default_service_account: + def test_gke_no_clusters(self): + gke_client = mock.MagicMock + gke_client.clusters = {} + + with mock.patch( + "prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account.gke_client", + new=gke_client, + ): + from prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account import ( + gke_cluster_no_default_service_account, + ) + + check = gke_cluster_no_default_service_account() + result = check.execute() + assert len(result) == 0 + + def test_one_cluster_without_node_pool(self): + + clusters = { + "123": Cluster( + name="test", + id="123", + location="eu-west-1", + service_account="default", + node_pools=[], + project_id=GCP_PROJECT_ID, + ) + } + + gke_client = mock.MagicMock + gke_client.project_ids = [GCP_PROJECT_ID] + gke_client.clusters = clusters + gke_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account.gke_client", + new=gke_client, + ): + from prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account import ( + gke_cluster_no_default_service_account, + ) + + check = gke_cluster_no_default_service_account() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"GKE cluster {clusters['123'].name} is using the Compute Engine default service account." + ) + assert result[0].project_id == clusters["123"].project_id + assert result[0].resource_id == clusters["123"].id + assert result[0].resource_name == clusters["123"].name + assert result[0].location == clusters["123"].location + + def test_one_cluster_without_node_pool_without_default_sa(self): + + clusters = { + "123": Cluster( + name="test", + id="123", + location="eu-west-1", + service_account="1231231231", + node_pools=[], + project_id=GCP_PROJECT_ID, + ) + } + + gke_client = mock.MagicMock + gke_client.project_ids = [GCP_PROJECT_ID] + gke_client.clusters = clusters + gke_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account.gke_client", + new=gke_client, + ): + from prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account import ( + gke_cluster_no_default_service_account, + ) + + check = gke_cluster_no_default_service_account() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"GKE cluster {clusters['123'].name} is not using the Compute Engine default service account." + ) + assert result[0].project_id == clusters["123"].project_id + assert result[0].resource_id == clusters["123"].id + assert result[0].resource_name == clusters["123"].name + assert result[0].location == clusters["123"].location + + def test_one_cluster_with_node_pool_with_default_sa(self): + + clusters = { + "123": Cluster( + name="test", + id="123", + location="eu-west-1", + service_account="default", + node_pools=[ + NodePool( + name="test", + locations=["eu-west-1"], + service_account="default", + project_id=GCP_PROJECT_ID, + ) + ], + project_id=GCP_PROJECT_ID, + ) + } + + gke_client = mock.MagicMock + gke_client.project_ids = [GCP_PROJECT_ID] + gke_client.clusters = clusters + gke_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account.gke_client", + new=gke_client, + ): + from prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account import ( + gke_cluster_no_default_service_account, + ) + + check = gke_cluster_no_default_service_account() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"GKE cluster {clusters['123'].name} is using the Compute Engine default service account." + ) + assert result[0].project_id == clusters["123"].project_id + assert result[0].resource_id == clusters["123"].id + assert result[0].resource_name == clusters["123"].name + assert result[0].location == clusters["123"].location + + def test_one_cluster_with_node_pool_with_non_default_sa(self): + + clusters = { + "123": Cluster( + name="test", + id="123", + location="eu-west-1", + service_account="default", + node_pools=[ + NodePool( + name="test", + locations=["eu-west-1"], + service_account="123123123", + project_id=GCP_PROJECT_ID, + ) + ], + project_id=GCP_PROJECT_ID, + ) + } + + gke_client = mock.MagicMock + gke_client.project_ids = [GCP_PROJECT_ID] + gke_client.clusters = clusters + gke_client.region = "global" + + with mock.patch( + "prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account.gke_client", + new=gke_client, + ): + from prowler.providers.gcp.services.gke.gke_cluster_no_default_service_account.gke_cluster_no_default_service_account import ( + gke_cluster_no_default_service_account, + ) + + check = gke_cluster_no_default_service_account() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"GKE cluster {clusters['123'].name} is not using the Compute Engine default service account." + ) + assert result[0].project_id == clusters["123"].project_id + assert result[0].resource_id == clusters["123"].id + assert result[0].resource_name == clusters["123"].name + assert result[0].location == clusters["123"].location diff --git a/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py b/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py index 1aa51292..1d028322 100644 --- a/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py +++ b/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py @@ -2,8 +2,7 @@ from re import search from unittest import mock from prowler.providers.gcp.services.iam.iam_service import Setting - -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_iam_account_access_approval_enabled: diff --git a/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py b/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py index 1b01c0ee..446acebd 100644 --- a/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py +++ b/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_iam_audit_logs_enabled: diff --git a/tests/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled_test.py b/tests/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled_test.py similarity index 59% rename from tests/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled_test.py rename to tests/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled_test.py index 026e9f83..f4876f3d 100644 --- a/tests/providers/gcp/services/serviceusage/serviceusage_cloudasset_inventory_enabled/serviceusage_cloudasset_inventory_enabled_test.py +++ b/tests/providers/gcp/services/iam/iam_cloud_asset_inventory_enabled/iam_cloud_asset_inventory_enabled_test.py @@ -1,4 +1,3 @@ -from re import search from unittest import mock from prowler.providers.gcp.services.serviceusage.serviceusage_service import Service @@ -6,7 +5,7 @@ from prowler.providers.gcp.services.serviceusage.serviceusage_service import Ser GCP_PROJECT_ID = "123456789012" -class Test_serviceusage_cloudasset_inventory_enabled: +class Test_iam_cloud_asset_inventory_enabled: def test_serviceusage_no_active_services(self): serviceusage_client = mock.MagicMock serviceusage_client.active_services = {} @@ -14,20 +13,20 @@ class Test_serviceusage_cloudasset_inventory_enabled: serviceusage_client.region = "global" with mock.patch( - "prowler.providers.gcp.services.serviceusage.serviceusage_cloudasset_inventory_enabled.serviceusage_cloudasset_inventory_enabled.serviceusage_client", + "prowler.providers.gcp.services.iam.iam_cloud_asset_inventory_enabled.iam_cloud_asset_inventory_enabled.serviceusage_client", new=serviceusage_client, ): - from prowler.providers.gcp.services.serviceusage.serviceusage_cloudasset_inventory_enabled.serviceusage_cloudasset_inventory_enabled import ( - serviceusage_cloudasset_inventory_enabled, + from prowler.providers.gcp.services.iam.iam_cloud_asset_inventory_enabled.iam_cloud_asset_inventory_enabled import ( + iam_cloud_asset_inventory_enabled, ) - check = serviceusage_cloudasset_inventory_enabled() + check = iam_cloud_asset_inventory_enabled() result = check.execute() assert len(result) == 1 assert result[0].status == "FAIL" - assert search( - f"Cloud Asset Inventory is not enabled in project {GCP_PROJECT_ID}", - result[0].status_extended, + assert ( + result[0].status_extended + == f"Cloud Asset Inventory is not enabled in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == "cloudasset.googleapis.com" assert result[0].project_id == GCP_PROJECT_ID @@ -49,20 +48,20 @@ class Test_serviceusage_cloudasset_inventory_enabled: serviceusage_client.region = "global" with mock.patch( - "prowler.providers.gcp.services.serviceusage.serviceusage_cloudasset_inventory_enabled.serviceusage_cloudasset_inventory_enabled.serviceusage_client", + "prowler.providers.gcp.services.iam.iam_cloud_asset_inventory_enabled.iam_cloud_asset_inventory_enabled.serviceusage_client", new=serviceusage_client, ): - from prowler.providers.gcp.services.serviceusage.serviceusage_cloudasset_inventory_enabled.serviceusage_cloudasset_inventory_enabled import ( - serviceusage_cloudasset_inventory_enabled, + from prowler.providers.gcp.services.iam.iam_cloud_asset_inventory_enabled.iam_cloud_asset_inventory_enabled import ( + iam_cloud_asset_inventory_enabled, ) - check = serviceusage_cloudasset_inventory_enabled() + check = iam_cloud_asset_inventory_enabled() result = check.execute() assert len(result) == 1 assert result[0].status == "PASS" - assert search( - f"Cloud Asset Inventory is enabled in project {GCP_PROJECT_ID}", - result[0].status_extended, + assert ( + result[0].status_extended + == f"Cloud Asset Inventory is enabled in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == "cloudasset.googleapis.com" assert result[0].project_id == GCP_PROJECT_ID diff --git a/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py b/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py index 21518e6e..ec9cb716 100644 --- a/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py +++ b/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_iam_no_service_roles_at_project_level: diff --git a/tests/providers/gcp/services/iam/iam_organization_essential_contacts_configured/iam_organization_essential_contacts_configured_test.py b/tests/providers/gcp/services/iam/iam_organization_essential_contacts_configured/iam_organization_essential_contacts_configured_test.py index f42856b7..e7c8377d 100644 --- a/tests/providers/gcp/services/iam/iam_organization_essential_contacts_configured/iam_organization_essential_contacts_configured_test.py +++ b/tests/providers/gcp/services/iam/iam_organization_essential_contacts_configured/iam_organization_essential_contacts_configured_test.py @@ -3,8 +3,6 @@ from unittest import mock from prowler.providers.gcp.services.iam.iam_service import Organization -GCP_PROJECT_ID = "123456789012" - class Test_iam_organization_essential_contacts_configured: def test_iam_no_organizations(self): diff --git a/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py b/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py index 74c12ff0..60551a14 100644 --- a/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py +++ b/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_iam_role_kms_enforce_separation_of_duties: diff --git a/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py b/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py index 78e9cc46..29c6eadc 100644 --- a/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py +++ b/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py @@ -1,7 +1,7 @@ from re import search from unittest import mock -GCP_PROJECT_ID = "123456789012" +from tests.providers.gcp.lib.audit_info_utils import GCP_PROJECT_ID class Test_iam_role_sa_enforce_separation_of_duties: