docs(dev-guide): improve quality redrive (#7718)

Co-authored-by: Rubén De la Torre Vico <ruben@prowler.com>
Co-authored-by: Daniel Barranquero <danielbo2001@gmail.com>
Co-authored-by: Andoni Alonso <14891798+andoniaf@users.noreply.github.com>
Co-authored-by: Rubén De la Torre Vico <rubendltv22@gmail.com>
This commit is contained in:
authored and GitHub committed 2025-06-17 09:28:22 +02:00
1 parent a0d169470d
commit e8a829b75e
12 files changed
+1218 -986

No files matched your search

+71 -173
View File
@@ -1,187 +1,78 @@
# Create a new Provider for Prowler
Here you can find how to create a new Provider in Prowler to give support for making all security checks needed and make your cloud safer!
# Prowler Providers
## Introduction
Providers are the foundation on which Prowler is built, a simple definition for a cloud provider could be "third-party company that offers a platform where any IT resource you need is available at any time upon request". The most well-known cloud providers are Amazon Web Services, Azure from Microsoft and Google Cloud which are already supported by Prowler.
Providers form the backbone of Prowler, enabling security assessments across various cloud environments.
To create a new provider that is not supported now by Prowler and add your security checks you must create a new folder to store all the related files within it (services, checks, etc.). It must be store in route `prowler/providers/<new_provider_name>/`.
A provider is any platform or service that offers resources, data, or functionality that can be audited for security and compliance. This includes:
Inside that folder, you MUST create the following files and folders:
- Cloud Infrastructure Providers (like Amazon Web Services, Microsoft Azure, and Google Cloud)
- Software as a Service (SaaS) Platforms (like Microsoft 365)
- Development Platforms (like GitHub)
- Container Orchestration Platforms (like Kubernetes)
- A `lib` folder: to store all extra functions.
- A `services` folder: to store all [services](./services.md) to audit.
- An empty `__init__.py`: to make Python treat this service folder as a package.
- A `<new_provider_name>_provider.py`, containing all the provider's logic necessary to get authenticated in the provider, configurations and extra data useful for final report.
- A `models.py`, containing all the models necessary for the new provider.
For providers supported by Prowler, refer to [Prowler Hub](https://hub.prowler.com/).
## Provider
???+ important
There are some custom providers added by the community, like [NHN Cloud](https://www.nhncloud.com/), that are not maintained by the Prowler team, but can be used in the Prowler CLI. They can be checked directly at the [Prowler GitHub repository](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers).
The structure for Prowler's providers is set up in such a way that they can be utilized through a generic service specific to each provider. This is achieved by passing the required parameters to the constructor, which in turn initializes all the necessary session values.
## Adding a New Provider
To integrate an unsupported Prowler provider and implement its security checks, create a dedicated folder for all related files (e.g., services, checks)."
This folder must be placed within [`prowler/providers/<new_provider_name>/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers).
Within this folder the following folders are also to be created:
- `lib` – Stores additional utility functions and core files required by every provider. The following files and subfolders are commonly found in every provider's `lib` folder:
- `service/service.py` – Provides a generic service class to be inherited by all services.
- `arguments/arguments.py` – Handles provider-specific argument parsing.
- `mutelist/mutelist.py` – Manages the mutelist functionality for the provider.
- `services` – Stores all [services](./services.md) that the provider offers and want to be audited by [Prowler checks](./checks.md).
- `__init__.py` (empty) – Ensures Python recognizes this folder as a package.
- `<new_provider_name>_provider.py` – Defines authentication logic, configurations, and other provider-specific data.
- `models.py` – Contains necessary models for the new provider.
By adhering to this structure, Prowler can effectively support services and security checks for additional providers.
???+ important
If your new provider requires a Python library (such as an official SDK or API client) to connect to its services, make sure to add it as a dependency in the `pyproject.toml` file. This ensures that all contributors and users have the necessary packages installed when working with your provider.
## Provider Structure in Prowler
Prowler's provider architecture is designed to facilitate security audits through a generic service tailored to each provider. This is accomplished by passing the necessary parameters to the constructor, which initializes all required session values.
### Base Class
All the providers in Prowler inherits from the same [base class](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/common/provider.py). It is an [abstract base class](https://docs.python.org/3/library/abc.html) that defines the interface for all provider classes. The code of the class is the next:
```python title="Provider Base Class"
from abc import ABC, abstractmethod
from typing import Any
class Provider(ABC):
"""
The Provider class is an abstract base class that defines the interface for all provider classes in the auditing system.
Attributes:
type (property): The type of the provider.
identity (property): The identity of the provider for auditing.
session (property): The session of the provider for auditing.
audit_config (property): The audit configuration of the provider.
output_options (property): The output configuration of the provider for auditing.
Methods:
print_credentials(): Displays the provider's credentials used for auditing in the command-line interface.
setup_session(): Sets up the session for the provider.
validate_arguments(): Validates the arguments for the provider.
get_checks_to_execute_by_audit_resources(): Returns a set of checks based on the input resources to scan.
Note:
This is an abstract base class and should not be instantiated directly. Each provider should implement its own
version of the Provider class by inheriting from this base class and implementing the required methods and properties.
"""
@property
@abstractmethod
def type(self) -> str:
"""
type method stores the provider's type.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@property
@abstractmethod
def identity(self) -> str:
"""
identity method stores the provider's identity to audit.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@abstractmethod
def setup_session(self) -> Any:
"""
setup_session sets up the session for the provider.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@property
@abstractmethod
def session(self) -> str:
"""
session method stores the provider's session to audit.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@property
@abstractmethod
def audit_config(self) -> str:
"""
audit_config method stores the provider's audit configuration.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@abstractmethod
def print_credentials(self) -> None:
"""
print_credentials is used to display in the CLI the provider's credentials used to audit.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@property
@abstractmethod
def output_options(self) -> str:
"""
output_options method returns the provider's audit output configuration.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@output_options.setter
@abstractmethod
def output_options(self, value: str) -> Any:
"""
output_options.setter sets the provider's audit output configuration.
This method needs to be created in each provider.
"""
raise NotImplementedError()
def validate_arguments(self) -> None:
"""
validate_arguments validates the arguments for the provider.
This method can be overridden in each provider if needed.
"""
raise NotImplementedError()
def get_checks_to_execute_by_audit_resources(self) -> set:
"""
get_checks_to_execute_by_audit_resources returns a set of checks based on the input resources to scan.
This is a fallback that returns None if the service has not implemented this function.
"""
return set()
@property
@abstractmethod
def mutelist(self):
"""
mutelist method returns the provider's mutelist.
This method needs to be created in each provider.
"""
raise NotImplementedError()
@mutelist.setter
@abstractmethod
def mutelist(self, path: str):
"""
mutelist.setter sets the provider's mutelist.
This method needs to be created in each provider.
"""
raise NotImplementedError()
```
All Prowler providers inherit from the same base class located in [`prowler/providers/common/provider.py`](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/common/provider.py). It is an [abstract base class](https://docs.python.org/3/library/abc.html) that defines the interface for all provider classes.
### Provider Class
Due to the complexity and differences of each provider use the rest of the providers as a template for the implementation.
#### Provider Implementation Guidance
Given the complexity and variability of providers, use existing provider implementations as templates when developing new integrations.
- [AWS](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/aws/aws_provider.py)
- [GCP](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/gcp/gcp_provider.py)
- [Azure](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/azure/azure_provider.py)
- [Kubernetes](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/kubernetes/kubernetes_provider.py)
- [M365](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/m365/m365_provider.py)
- [Microsoft365](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/microsoft365/microsoft365_provider.py)
- [GitHub](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/github/github_provider.py)
To facilitate understanding here is a pseudocode of how the most basic provider could be with examples.
### Basic Provider Implementation: Pseudocode Example
To simplify understanding, the following pseudocode outlines the fundamental structure of a provider, including library imports necessary for authentication.
```python title="Provider Example Class"
# Library imports to authenticate in the Provider
# Library Imports for Authentication
# When implementing authentication for a provider, import the required libraries.
from prowler.config.config import load_and_validate_config_file
from prowler.lib.logger import logger
@@ -190,14 +81,14 @@ from prowler.lib.utils.utils import print_boxes
from prowler.providers.common.models import Audit_Metadata
from prowler.providers.common.provider import Provider
from prowler.providers.<new_provider_name>.models import (
# All providers models needed
# All provider models needed.
ProviderSessionModel,
ProviderIdentityModel,
ProviderOutputOptionsModel
)
class NewProvider(Provider):
# All properties from the class, some of this are properties in the base class
# All properties from the class, some of which are properties in the base class.
_type: str = "<provider_name>"
_session: <ProviderSessionModel>
_identity: <ProviderIdentityModel>
@@ -213,20 +104,30 @@ class NewProvider(Provider):
arguments (dict): A dictionary containing configuration arguments.
"""
logger.info("Setting <NewProviderName> provider ...")
# First get from arguments the necessary from the cloud account (subscriptions or projects or whatever the provider use for storing services)
# Set the session with the method enforced by parent class
# Initializing the Provider Session
# Steps:
# - Retrieve Account Information
# - Extract relevant account identifiers (subscriptions, projects, or other service references) from the provided arguments.
# Establish a Session
# Use the method enforced by the parent class to set up the session:
self._session = self.setup_session(credentials_file)
# Set the Identity class normaly the provider class give by Python provider library
# Define Provider Identity
# Assign the identity class, typically provided by the Python provider library:
self._identity = <ProviderIdentityModel>()
# Set the provider configuration
# Configure the Provider
# Set the provider-specific configuration.
self._audit_config = load_and_validate_config_file(
self._type, arguments.config_file
)
# All enforced properties by the parent class
# All the enforced properties by the parent class.
@property
def identity(self):
return self._identity
@@ -252,7 +153,7 @@ class NewProvider(Provider):
Sets up the Provider session.
Args:
<all_needed_for_auth> Can include all necessary arguments to setup the session
<all_needed_for_auth> Can include all necessary arguments to set up the session
Returns:
Credentials necessary to communicate with the provider.
@@ -262,11 +163,8 @@ class NewProvider(Provider):
"""
This method is enforced by parent class and is used to print all relevant
information during the prowler execution as a header of execution.
Normally the Account ID, User name or stuff like this is displayed in colors using the colorama module (Fore).
Displaying Account Information with Color Formatting. In Prowler, Account IDs, usernames, and other identifiers are typically displayed using color formatting provided by the colorama module (Fore).
"""
def print_credentials(self):
pass
```