chore(azure): working version executing checks (#3474)

This commit is contained in:
Pepe Fagoaga
2024-03-01 13:30:09 +01:00
committed by GitHub
parent b48b3a5e2e
commit be55fa22fd
22 changed files with 86 additions and 153 deletions
-1
View File
@@ -190,7 +190,6 @@ def prowler():
mutelist_file = global_provider.get_mutelist(args.mutelist_file)
# Set output options based on the selected provider
# TODO: this is going to be removed an include in the Provider as a new common object
audit_output_options = set_provider_output_options(
provider, args, global_provider.identity, mutelist_file, bulk_checks_metadata
+2
View File
@@ -522,10 +522,12 @@ def execute_checks(
# If check does not exists in the provider or is from another provider
except ModuleNotFoundError:
# TODO: add more loggin here, we need the original exception -- traceback.print_last()
logger.error(
f"Check '{check_name}' was not found for the {global_provider.provider.upper()} provider"
)
except Exception as error:
# TODO: add more loggin here, we need the original exception -- traceback.print_last()
logger.error(
f"{check_name} - {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
+1
View File
@@ -40,6 +40,7 @@ from prowler.providers.aws.models import (
from prowler.providers.common.provider import Provider
# TODO: why do we have variables defined in the class not passed to the __init__???
class AwsProvider(Provider):
session: AWSSession = AWSSession(
session=None, session_config=None, original_session=None
@@ -15,6 +15,7 @@ from prowler.providers.azure.models import AzureIdentityInfo, AzureRegionConfig
from prowler.providers.common.provider import Provider
# TODO: why do we have variables defined in the class not passed to the __init__???
class AzureProvider(Provider):
session: DefaultAzureCredential
identity: AzureIdentityInfo
+4 -2
View File
@@ -103,7 +103,7 @@ class Azure_Output_Options(Provider_Output_Options):
class Gcp_Output_Options(Provider_Output_Options):
def __init__(self, arguments, audit_info, mutelist_file, bulk_checks_metadata):
def __init__(self, arguments, identity, mutelist_file, bulk_checks_metadata):
# First call Provider_Output_Options init
super().__init__(arguments, mutelist_file, bulk_checks_metadata)
@@ -112,7 +112,9 @@ class Gcp_Output_Options(Provider_Output_Options):
not hasattr(arguments, "output_filename")
or arguments.output_filename is None
):
self.output_filename = f"prowler-output-{getattr(audit_info.credentials, '_service_account_email', 'default')}-{output_file_timestamp}"
self.output_filename = (
f"prowler-output-{identity.profile}-{output_file_timestamp}"
)
else:
self.output_filename = arguments.output_filename
+46 -13
View File
@@ -1,23 +1,41 @@
import os
import sys
from dataclasses import dataclass
from typing import Any, Optional
from colorama import Fore, Style
from google import auth
from google.oauth2.credentials import Credentials
from googleapiclient import discovery
from prowler.lib.logger import logger
from prowler.providers.common.provider import Provider
class GCP_Provider:
def __init__(
self,
credentials_file: str,
input_project_ids: list,
):
@dataclass
class GCPIdentityInfo:
profile: str
# TODO: why do we have variables defined in the class not passed to the __init__???
class GcpProvider(Provider):
# TODO: should we move session and identity to the Provider parent class?
provider = "gcp"
session: Credentials
default_project_id: str
project_ids: list
# TODO: review this since we have to create an identity object
identity: GCPIdentityInfo
audit_resources: Optional[Any]
audit_metadata: Optional[Any]
audit_config: Optional[dict]
def __init__(self, arguments):
logger.info("Instantiating GCP Provider ...")
self.credentials, self.default_project_id = self.__set_credentials__(
credentials_file
)
input_project_ids = arguments.project_ids
credentials_file = arguments.credentials_file
self.session, self.default_project_id = self.setup_session(credentials_file)
self.project_ids = []
accessible_projects = self.get_project_ids()
@@ -38,7 +56,15 @@ class GCP_Provider:
# If not projects were input, all accessible projects are scanned by default
self.project_ids = accessible_projects
def __set_credentials__(self, credentials_file):
self.identity = GCPIdentityInfo(
profile=getattr(self.session, "_service_account_email", "default")
)
# TODO: move this to the parent class or the main
if not arguments.only_logs:
self.print_credentials()
def setup_session(self, credentials_file):
try:
if credentials_file:
self.__set_gcp_creds_env_var__(credentials_file)
@@ -59,15 +85,22 @@ class GCP_Provider:
client_secrets_path = os.path.abspath(credentials_file)
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = client_secrets_path
def get_credentials(self):
return self.credentials, self.default_project_id, self.project_ids
def print_credentials(self):
# Beautify audited profile, set "default" if there is no profile set
report = f"""
This report is being generated using credentials below:
GCP Account: {Fore.YELLOW}[{self.identity.profile}]{Style.RESET_ALL} GCP Project IDs: {Fore.YELLOW}[{", ".join(self.project_ids)}]{Style.RESET_ALL}
"""
print(report)
def get_project_ids(self):
try:
project_ids = []
service = discovery.build(
"cloudresourcemanager", "v1", credentials=self.credentials
"cloudresourcemanager", "v1", credentials=self.session
)
request = service.projects().list()
-119
View File
@@ -1,119 +0,0 @@
import os
import sys
from typing import Any, Optional
from colorama import Fore, Style
from google import auth
from google.oauth2.credentials import Credentials
from googleapiclient import discovery
from prowler.lib.logger import logger
from prowler.providers.common.provider import Provider
class GcpProvider(Provider):
session: Credentials
default_project_id: str
project_ids: list
audit_resources: Optional[Any]
audit_metadata: Optional[Any]
audit_config: Optional[dict]
def __init__(self, arguments):
logger.info("Instantiating GCP Provider ...")
input_project_ids = arguments.project_ids
credentials_file = arguments.credentials_file
self.session, self.default_project_id = self.setup_session(credentials_file)
if not self.default_project_id:
logger.critical("No Project ID associated to Google Credentials.")
sys.exit(1)
self.project_ids = []
accessible_projects = self.get_project_ids()
if not accessible_projects:
logger.critical("No Project IDs can be accessed via Google Credentials.")
sys.exit(1)
if input_project_ids:
for input_project in input_project_ids:
if input_project in accessible_projects:
self.project_ids.append(input_project)
else:
logger.critical(
f"Project {input_project} cannot be accessed via Google Credentials."
)
sys.exit(1)
else:
# If not projects were input, all accessible projects are scanned by default
self.project_ids = accessible_projects
if not arguments.only_logs:
self.print_credentials()
def setup_session(self, credentials_file):
try:
if credentials_file:
self.__set_gcp_creds_env_var__(credentials_file)
return auth.default(
scopes=["https://www.googleapis.com/auth/cloud-platform"]
)
except Exception as error:
logger.critical(
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
sys.exit(1)
def __set_gcp_creds_env_var__(self, credentials_file):
logger.info(
"GCP provider: Setting GOOGLE_APPLICATION_CREDENTIALS environment variable..."
)
client_secrets_path = os.path.abspath(credentials_file)
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = client_secrets_path
def print_credentials(self):
# Beautify audited profile, set "default" if there is no profile set
try:
getattr(self.session, "_service_account_email")
profile = (
self.session._service_account_email
if self.session._service_account_email is not None
else "default"
)
except AttributeError:
profile = "default"
report = f"""
This report is being generated using credentials below:
GCP Account: {Fore.YELLOW}[{profile}]{Style.RESET_ALL} GCP Project IDs: {Fore.YELLOW}[{", ".join(self.project_ids)}]{Style.RESET_ALL}
"""
print(report)
def get_project_ids(self):
try:
project_ids = []
service = discovery.build(
"cloudresourcemanager", "v1", credentials=self.session
)
request = service.projects().list()
while request is not None:
response = request.execute()
for project in response.get("projects", []):
project_ids.append(project["projectId"])
request = service.projects().list_next(
previous_request=request, previous_response=response
)
return project_ids
except Exception as error:
logger.error(
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
return []
+1 -1
View File
@@ -8,7 +8,7 @@ from googleapiclient import discovery
from googleapiclient.discovery import Resource
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider_new import GcpProvider
from prowler.providers.gcp.gcp_provider import GcpProvider
class GCPService:
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## API Keys
class APIKeys(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider, api_version="v2")
self.keys = []
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## BigQuery
class BigQuery(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider, api_version="v2")
self.datasets = []
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## CloudResourceManager
class CloudResourceManager(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.bindings = []
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## CloudSQL
class CloudSQL(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__("sqladmin", provider)
self.instances = []
self.__get_instances__()
@@ -3,12 +3,13 @@ from typing import Optional
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## CloudStorage
class CloudStorage(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__("storage", provider)
self.buckets = []
self.__get_buckets__()
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## Compute
class Compute(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.regions = set()
self.zones = set()
@@ -1,13 +1,14 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
from prowler.providers.gcp.services.compute.compute_client import compute_client
################## Dataproc
class Dataproc(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.regions = compute_client.regions
self.clusters = []
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## DNS
class DNS(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.managed_zones = []
self.__get_managed_zones__()
@@ -1,13 +1,14 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## GKE
class GKE(GCPService):
def __init__(self, provider):
super().__init__("container", audit_info, api_version="v1beta1")
def __init__(self, provider: GcpProvider):
super().__init__("container", provider, api_version="v1beta1")
self.locations = []
self.__get_locations__()
self.clusters = {}
@@ -3,6 +3,7 @@ from datetime import datetime
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
from prowler.providers.gcp.services.cloudresourcemanager.cloudresourcemanager_client import (
cloudresourcemanager_client,
@@ -11,7 +12,7 @@ from prowler.providers.gcp.services.cloudresourcemanager.cloudresourcemanager_cl
################## IAM
class IAM(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.service_accounts = []
self.__get_service_accounts__()
@@ -103,7 +104,7 @@ class ServiceAccount(BaseModel):
################## AccessApproval
class AccessApproval(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.settings = {}
self.__get_settings__()
@@ -135,7 +136,7 @@ class Setting(BaseModel):
################## EssentialContacts
class EssentialContacts(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.organizations = []
self.__get_contacts__()
@@ -3,12 +3,13 @@ from typing import Optional
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## KMS
class KMS(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__("cloudkms", provider)
self.locations = []
self.key_rings = []
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## Logging
class Logging(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider, api_version="v2")
self.sinks = []
self.metrics = []
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## Monitoring
class Monitoring(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider, api_version="v3")
self.alert_policies = []
self.__get_alert_policies__()
@@ -1,12 +1,13 @@
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.gcp.gcp_provider import GcpProvider
from prowler.providers.gcp.lib.service.service import GCPService
################## ServiceUsage
class ServiceUsage(GCPService):
def __init__(self, provider):
def __init__(self, provider: GcpProvider):
super().__init__(__class__.__name__, provider)
self.active_services = {}
self.__get_active_services__()