feat(threatscore): support user token

This commit is contained in:
pedrooot
2025-07-02 11:50:44 +02:00
parent 76e058f28f
commit 878f4857af
2 changed files with 70 additions and 43 deletions

View File

@@ -1,11 +1,11 @@
# ThreatScore Compliance Report Generator
This tool generates a PDF compliance report using Prowler's API endpoints, summarizing compliance requirements, risk levels, and findings for a given scan and compliance framework.
This tool generates a compliance PDF report using Prowler's API endpoints, summarizing requirements, risk levels, and findings for a given scan and compliance framework.
## Features
- Authenticates with the Prowler API using email and password
- Retrieves compliance requirements and attributes for a given scan and compliance framework
- Generates a visually rich PDF report, including:
- Authenticate with the Prowler API using email+password or token
- Retrieve compliance requirements and attributes for a given scan and framework
- Generate a visually rich PDF report, including:
- Compliance summary and description
- Compliance score by section (with charts)
- Critical failed requirements (with risk and weight)
@@ -23,30 +23,34 @@ pip install matplotlib requests reportlab
## Usage
```bash
python3 util/compliance_report/generate_threatscore_report.py \
python3 util/compliance_report/threatscore_report_generator.py \
--scan-id <scan_id> \
--compliance-id <compliance_id> \
--email <email> \
--password <password> \
[--token <token>] \
[--output <output_path>] \
[--base-url <base_url>] \
[--only-failed] \
[--min-risk-level <level>]
```
> **Note:** You must provide either both `--email` and `--password`, or a `--token`. One of these authentication methods is required. If you provide a token, email and password are ignored.
### Arguments
- `--scan-id` (required): ID of the scan executed by Prowler.
- `--compliance-id` (required): Compliance framework ID (e.g., `prowler_threatscore_azure`, `nis2_azure`).
- `--email` (required): Email for API authentication.
- `--password` (required): Password for API authentication.
- `--email` (required*): Email for API authentication (*required if `--token` is not used).
- `--password` (required*): Password for API authentication (*required if `--token` is not used).
- `--token` (required*): JWT token for authentication (*required if `--email` and `--password` are not used).
- `--output` (optional): Output PDF file path (default: `threatscore_report.pdf`).
- `--base-url` (optional): Base URL for the API (default: `http://localhost:8080`).
- `--only-failed` (optional): Only include failed requirements in the report.
- `--min-risk-level` (optional): Minimum risk level for critical failed requirements (default: 4).
- `--min-risk-level` (optional): Minimum risk level to show critical failed requirements (default: 4).
### Example
```bash
python3 util/compliance_report/generate_threatscore_report.py \
python3 util/compliance_report/threatscore_report_generator.py \
--scan-id 12345678-1234-5678-1234-567812345678 \
--compliance-id prowler_threatscore_azure \
--email user@example.com \
@@ -57,6 +61,15 @@ python3 util/compliance_report/generate_threatscore_report.py \
--min-risk-level 4
```
Or using a token:
```bash
python3 util/compliance_report/threatscore_report_generator.py \
--scan-id 12345678-1234-5678-1234-567812345678 \
--compliance-id prowler_threatscore_azure \
--token eyJhbGciOi... \
--output my_report.pdf
```
## Output
- The script will generate a PDF file with:
- Compliance framework summary
@@ -65,6 +78,6 @@ python3 util/compliance_report/generate_threatscore_report.py \
- Detailed breakdown of each requirement and its findings
## Notes
- The script authenticates with the API and retrieves all necessary data automatically.
- If you encounter authentication errors, check your email, password, and API URL.
- For more details, see the script source: `util/compliance_report/generate_threatscore_report.py`
- The script can authenticate with email/password or directly with a JWT token. **One of these authentication methods is mandatory.**
- If you encounter authentication errors, check your credentials, token, and API URL.
- For more details, see the source code: `util/compliance_report/threatscore_report_generator.py`

View File

@@ -44,6 +44,7 @@ def generate_threatscore_report(
output_path: str,
email: str,
password: str,
token: str,
base_url: str,
only_failed: bool = True,
min_risk_level: int = 4,
@@ -57,6 +58,7 @@ def generate_threatscore_report(
- output_path: Output PDF file path (e.g., "threatscore_report.pdf").
- email: Email for the API authentication.
- password: Password for the API.
- token: Token for the API.
- base_url: Base URL for the API.
- only_failed: If True, only requirements with status "FAIL" will be included in the list of requirements.
- min_risk_level: Minimum risk level for critical failed requirements.
@@ -134,40 +136,46 @@ def generate_threatscore_report(
textColor=colors.Color(0.2, 0.2, 0.2),
fontName="PlusJakartaSans",
)
url_credentials = f"{base_url}/api/v1/tokens"
payload = {
"data": {
"type": "tokens",
"attributes": {
"email": email,
"password": password,
},
if not token:
if not email or not password:
raise Exception("Email and password are required to generate a token")
url_credentials = f"{base_url}/api/v1/tokens"
payload = {
"data": {
"type": "tokens",
"attributes": {
"email": email,
"password": password,
},
}
}
}
resp_credentials = requests.post(
url_credentials,
json=payload,
headers={"Content-Type": "application/vnd.api+json"},
).json()
if resp_credentials.get("errors"):
print(resp_credentials.get("errors"))
raise Exception(resp_credentials.get("errors"))
token = resp_credentials.get("data", {}).get("attributes", {}).get("access")
resp_credentials = requests.post(
url_credentials,
json=payload,
headers={"Content-Type": "application/vnd.api+json"},
).json()
if resp_credentials.get("errors"):
print(resp_credentials.get("errors"))
raise Exception(resp_credentials.get("errors"))
token = resp_credentials.get("data", {}).get("attributes", {}).get("access")
url_reqs = f"{base_url}/api/v1/compliance-overviews/requirements?filter[compliance_id]={compliance_id}&filter[scan_id]={scan_id}"
resp_reqs = (
requests.get(url_reqs, headers={"Authorization": f"Bearer {token}"})
.json()
.get("data", [])
)
try:
url_reqs = f"{base_url}/api/v1/compliance-overviews/requirements?filter[compliance_id]={compliance_id}&filter[scan_id]={scan_id}"
resp_reqs = (
requests.get(url_reqs, headers={"Authorization": f"Bearer {token}"})
.json()
.get("data", [])
)
url_attrs = f"{base_url}/api/v1/compliance-overviews/attributes?filter[compliance_id]={compliance_id}"
resp_attrs = (
requests.get(url_attrs, headers={"Authorization": f"Bearer {token}"})
.json()
.get("data", [])
)
url_attrs = f"{base_url}/api/v1/compliance-overviews/attributes?filter[compliance_id]={compliance_id}"
resp_attrs = (
requests.get(url_attrs, headers={"Authorization": f"Bearer {token}"})
.json()
.get("data", [])
)
except Exception as e:
print(e)
raise Exception(e)
compliance_name = resp_reqs[0]["attributes"]["framework"]
compliance_version = resp_reqs[0]["attributes"]["version"]
@@ -876,6 +884,11 @@ if __name__ == "__main__":
action="store_true",
help="Only include failed requirements in the list of requirements",
)
parser.add_argument(
"--token",
default="",
help="Token for the API",
)
parser.add_argument(
"--base-url",
default="http://localhost:8080",
@@ -895,6 +908,7 @@ if __name__ == "__main__":
args.output,
args.email,
args.password,
args.token,
args.base_url,
args.only_failed,
args.min_risk_level,