feat(microsof365): Add documentation and compliance file (#6195)

Co-authored-by: MrCloudSec <hello@mistercloudsec.com>
Co-authored-by: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com>
This commit is contained in:
Mario Rodriguez Lopez
2025-02-10 17:13:06 +01:00
committed by GitHub
parent ff35fd90fa
commit dcb9267c2f
12 changed files with 161 additions and 8 deletions

View File

@@ -75,6 +75,7 @@ It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, Fe
| GCP | 77 | 13 | 4 | 3 |
| Azure | 140 | 18 | 5 | 3 |
| Kubernetes | 83 | 7 | 2 | 7 |
| Microsoft365 | 5 | 2 | 1 | 0 |
> You can list the checks, services, compliance frameworks and categories with `prowler <provider> --list-checks`, `prowler <provider> --list-services`, `prowler <provider> --list-compliance` and `prowler <provider> --list-categories`.

View File

@@ -175,6 +175,7 @@ Due to the complexity and differences of each provider use the rest of the provi
- [GCP](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/gcp/gcp_provider.py)
- [Azure](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/azure/azure_provider.py)
- [Kubernetes](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/kubernetes/kubernetes_provider.py)
- [Microsoft365](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/microsoft365/microsoft365_provider.py)
To facilitate understanding here is a pseudocode of how the most basic provider could be with examples.

View File

@@ -237,3 +237,4 @@ It is really important to check if the current Prowler's permissions for each pr
- AWS: https://docs.prowler.cloud/en/latest/getting-started/requirements/#aws-authentication
- Azure: https://docs.prowler.cloud/en/latest/getting-started/requirements/#permissions
- GCP: https://docs.prowler.cloud/en/latest/getting-started/requirements/#gcp-authentication
- Microsoft365: https://docs.prowler.cloud/en/latest/getting-started/requirements/#microsoft365-authentication

View File

@@ -102,3 +102,32 @@ Those credentials must be associated to a user or service account with proper pe
???+ note
By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
## Microsoft365
Prowler for Microsoft365 currently supports the following authentication types:
- [Service principal application](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser#service-principal-object) (recommended).
- Current az cli credentials stored.
- Interactive browser authentication.
???+ warning
For Prowler App only the Service Principal with an application authentication method is supported.
### Service Principal authentication
To allow Prowler assume the service principal identity to start the scan it is needed to configure the following environment variables:
```console
export AZURE_CLIENT_ID="XXXXXXXXX"
export AZURE_CLIENT_SECRET="XXXXXXXXX"
export AZURE_TENANT_ID="XXXXXXXXX"
```
If you try to execute Prowler with the `--sp-env-auth` flag and those variables are empty or not exported, the execution is going to fail.
Follow the instructions in the [Create Prowler Service Principal](../tutorials/azure/create-prowler-service-principal.md) section to create a service principal.
### Interactive Browser authentication
To use `--browser-auth` the user needs to authenticate against Azure using the default browser to start the scan, also `--tenant-id` flag is required.

View File

@@ -164,7 +164,7 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler/),
* `Python >= 3.9`
* `Python pip >= 21.0.0`
* AWS, GCP, Azure and/or Kubernetes credentials
* AWS, GCP, Azure, Microsoft365 and/or Kubernetes credentials
_Commands_:
@@ -417,7 +417,7 @@ While the scan is running, start exploring the findings in these sections:
### Prowler CLI
To run Prowler, you will need to specify the provider (e.g `aws`, `gcp`, `azure` or `kubernetes`):
To run Prowler, you will need to specify the provider (e.g `aws`, `gcp`, `azure`, `microsoft365` or `kubernetes`):
???+ note
If no provider specified, AWS will be used for backward compatibility with most of v2 options.
@@ -559,5 +559,23 @@ kubectl logs prowler-XXXXX --namespace prowler-ns
???+ note
By default, `prowler` will scan all namespaces in your active Kubernetes context. Use the flag `--context` to specify the context to be scanned and `--namespaces` to specify the namespaces to be scanned.
#### Microsoft365
With Microsoft365 you need to specify which auth method is going to be used:
```console
# To use service principal authentication
prowler microsoft365 --sp-env-auth
# To use az cli authentication
prowler microsoft365 --az-cli-auth
# To use browser authentication
prowler microsoft365 --browser-auth --tenant-id "XXXXXXXX"
```
See more details about Microsoft365 Authentication in [Requirements](getting-started/requirements.md#microsoft365)
## Prowler v2 Documentation
For **Prowler v2 Documentation**, please check it out [here](https://github.com/prowler-cloud/prowler/blob/8818f47333a0c1c1a457453c87af0ea5b89a385f/README.md).

View File

@@ -4,7 +4,7 @@ To allow Prowler assume an identity to start the scan with the required privileg
To create a Service Principal Application you can use the Azure Portal or the Azure CLI.
## From Azure Portal
## From Azure Portal / Entra Admin Center
1. Access to Microsoft Entra ID
2. In the left menu bar, go to "App registrations"

View File

@@ -0,0 +1,23 @@
# Microsoft365 authentication
By default Prowler uses MsGraph Python SDK identity package authentication methods using the class `ClientSecretCredential`.
This allows Prowler to authenticate against microsoft365 using the following methods:
- Service principal authentication by environment variables (Enterprise Application)
- Current CLI credentials stored
- Interactive browser authentication
To launch the tool first you need to specify which method is used through the following flags:
```console
# To use service principal authentication
prowler microsoft365 --sp-env-auth
# To use cli authentication
prowler microsoft365 --az-cli-auth
# To use browser authentication
prowler microsoft365 --browser-auth --tenant-id "XXXXXXXX"
```
To use Prowler you need to set up also the permissions required to access your resources in your Microsoft365 account, to more details refer to [Requirements](../../getting-started/requirements.md)

View File

@@ -94,6 +94,9 @@ nav:
- In-Cluster Execution: tutorials/kubernetes/in-cluster.md
- Non In-Cluster Execution: tutorials/kubernetes/outside-cluster.md
- Miscellaneous: tutorials/kubernetes/misc.md
- Microsoft 365:
- Authentication: tutorials/microsoft365/authentication.md
- Create Prowler Service Principal: tutorials/microsoft365/create-prowler-service-principal.md
- Developer Guide:
- Introduction: developer-guide/introduction.md
- Provider: developer-guide/provider.md

View File

@@ -123,7 +123,10 @@ def load_and_validate_config_file(provider: str, config_file_path: str) -> dict:
# Not to introduce a breaking change, allow the old format config file without any provider keys
# and a new format with a key for each provider to include their configuration values within.
if any(key in config_file for key in ["aws", "gcp", "azure", "kubernetes"]):
if any(
key in config_file
for key in ["aws", "gcp", "azure", "kubernetes", "microsoft365"]
):
config = config_file.get(provider, {})
else:
config = config_file if config_file else {}

View File

@@ -42,7 +42,7 @@ class Microsoft365CIS(ComplianceOutput):
compliance_row = Microsoft365CISModel(
Provider=finding.provider,
Description=compliance.Description,
SubscriptionId=finding.account_uid,
TenantId=finding.account_uid,
Location=finding.region,
AssessmentDate=str(finding.timestamp),
Requirements_Id=requirement.Id,
@@ -73,8 +73,8 @@ class Microsoft365CIS(ComplianceOutput):
compliance_row = Microsoft365CISModel(
Provider=compliance.Provider.lower(),
Description=compliance.Description,
SubscriptionId="",
Location="",
TenantId=finding.account_uid,
Location=finding.region,
AssessmentDate=str(finding.timestamp),
Requirements_Id=requirement.Id,
Requirements_Description=requirement.Description,

View File

@@ -73,7 +73,7 @@ class Microsoft365CISModel(BaseModel):
Provider: str
Description: str
SubscriptionId: str
TenantId: str
Location: str
AssessmentDate: str
Requirements_Id: str

View File

@@ -0,0 +1,74 @@
import csv
import json
import sys
# Convert a CSV file following the CIS 4.0 Microsoft365 Benchmark into a Prowler v3.0 Compliance JSON file
# CSV fields:
# Section #,Recommendation #,Profile,Title,Assessment Status,Description,Rationale Statement,Impact Statement,Remediation Procedure,Audit Procedure,Additional Information,CIS Controls,CIS Safeguards 1 (v8),CIS Safeguards 2 (v8),CIS Safeguards 3 (v8),v8 IG1,v8 IG2,v8 IG3,CIS Safeguards 1 (v7),CIS Safeguards 2 (v7),CIS Safeguards 3 (v7),v7 IG1,v7 IG2,v7 IG3,References,Default Value
# Get the CSV filename to convert from
file_name = sys.argv[1]
# Create the output JSON object
output = {"Framework": "CIS", "Version": "4.0", "Requirements": []}
# Open the CSV file and read the rows
try:
with open(file_name, newline="", encoding="utf-8") as f:
reader = csv.reader(f, delimiter=",")
next(reader) # Skip the header row
for row in reader:
attribute = {
"Section": row[0],
"Profile": row[2],
"AssessmentStatus": row[4],
"Description": row[5],
"RationaleStatement": row[6],
"ImpactStatement": row[7],
"RemediationProcedure": row[8],
"AuditProcedure": row[9],
"AdditionalInformation": row[10],
"References": row[24],
}
if row[4] != "":
output["Requirements"].append(
{
"Id": row[1],
"Description": row[5],
"Checks": [],
"Attributes": [attribute],
}
)
except UnicodeDecodeError:
# If there is an error reading the file with the default encoding, try with ISO-8859-1
with open(file_name, newline="", encoding="ISO-8859-1") as f:
reader = csv.reader(f, delimiter=",")
next(reader) # Skip the header row
for row in reader:
attribute = {
"Section": row[0],
"Profile": row[2],
"AssessmentStatus": row[4],
"Description": row[5],
"RationaleStatement": row[6],
"ImpactStatement": row[7],
"RemediationProcedure": row[8],
"AuditProcedure": row[9],
"AdditionalInformation": row[10],
"References": row[24],
}
if row[4] != "":
output["Requirements"].append(
{
"Id": row[1],
"Description": row[5],
"Checks": [],
"Attributes": [attribute],
}
)
# Save the output JSON file
with open("cis_4.0_microsoft365.json", "w", encoding="utf-8") as outfile:
json.dump(output, outfile, indent=4, ensure_ascii=False)
print("Archivo JSON generado exitosamente.")