Files
prowler/examples/sdk/aws_scan.ipynb
2025-04-15 13:24:09 -04:00

419 lines
16 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup and Configure Logger\n",
"This section configures the Python logging system to filter Prowler's output messages during security scans. We set the logging level to `CRITICAL`."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import logging\n",
"\n",
"logging.basicConfig(level=logging.CRITICAL)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Initialize AWS Provider"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import the Prowler's provider you want to scan\n",
"from prowler.providers.aws.aws_provider import AwsProvider\n",
"import json\n",
"\n",
"# Path to credentials file\n",
"credentials_path = \"./secrets-sdk/credentials.json\"\n",
"\n",
"# Load credentials from JSON file\n",
"try:\n",
" with open(credentials_path, \"r\") as f:\n",
" aws_credentials = json.load(f)\n",
" print(\"AWS credentials loaded successfully from file\")\n",
"except (FileNotFoundError, json.JSONDecodeError):\n",
" print(\"Invalid or missing JSON credentials file\")\n",
" aws_credentials = {\n",
" \"aws_access_key_id\": \"YOUR_ACCESS_KEY\",\n",
" \"aws_secret_access_key\": \"YOUR_SECRET_KEY\",\n",
" \"aws_session_token\": \"YOUR_SESSION_TOKEN\"\n",
" }\n",
"\n",
"# Optional: Test the AWS provider credentials before instantiation to verify that credentials work\n",
"aws_connection = AwsProvider.test_connection(**aws_credentials)\n",
"print(f\"AWS Test Connection:\\n\\t- Connected: {aws_connection.is_connected}\\n\\t- Error (if any): {aws_connection.error}\\n\")\n",
"\n",
"# Initialize the AWS provider with static credentials\n",
"aws = AwsProvider(**aws_credentials)\n",
"\n",
"# AWS Identity Information\n",
"print(f\"AWS Identity Information:\\n\\t- Account Number: {aws.identity.account}\\n\\t- User ID: {aws.identity.user_id}\\n\")\n",
"\n",
"# Alternative Providers (commented out)\n",
"# from prowler.providers.gcp.gcp_provider import GcpProvider\n",
"# from prowler.providers.azure.azure_provider import AzureProvider\n",
"# from prowler.providers.kubernetes.kubernetes_provider import KubernetesProvider\n",
"# from prowler.providers.m365.m365_provider import M365Provider"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pprint\n",
"pprint.pp(aws.identity)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mutelist"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Mutelist\n",
"from prowler.providers.aws.lib.mutelist.mutelist import AWSMutelist\n",
"\n",
"\n",
"mutelist_content = {\n",
" \"Accounts\": {\n",
" \"*\": {\n",
" \"Checks\": {\n",
" \"s3_account_level_public_access_blocks\": {\n",
" \"Tags\": [\"*\"],\n",
" \"Regions\": [\"*\"],\n",
" \"Resources\": [\"*\"],\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"mutelist_object = AWSMutelist(\n",
" mutelist_content=mutelist_content,\n",
")\n",
"aws._mutelist = mutelist_object"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## List Available Security Checks\n",
"Explore different ways to list security checks by provider, service, severity, and category."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import the CheckMetadata class to list security checks\n",
"from prowler.lib.check.models import CheckMetadata\n",
"\n",
"# List all available checks\n",
"checks = CheckMetadata.list()\n",
"print(f\"# Checks: {len(checks)}\")\n",
"\n",
"# List all AWS S3 checks\n",
"aws_s3_checks = CheckMetadata.list(provider=\"aws\", service=\"s3\")\n",
"print(f\"AWS S3 Checks:\\n\\t- {'\\n\\t- '.join(aws_s3_checks)}\")\n",
"\n",
"# List all critical severity checks\n",
"critical_checks = CheckMetadata.list(provider=\"aws\", severity=\"critical\")\n",
"print(f\"\\n# Critical Checks: {len(critical_checks)}\")\n",
"\n",
"# List all checks in the internet-exposed category\n",
"internet_exposed_checks = CheckMetadata.list(provider=\"aws\", category=\"internet-exposed\")\n",
"print(f\"\\n# Internet-Exposed Category Checks: {len(internet_exposed_checks)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Execute Security Scans\n",
"Set up and execute security scans on AWS resources with different filtering options."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import necessary libraries for scanning\n",
"from prowler.lib.scan.scan import Scan\n",
"# Auxiliary libraries\n",
"import itertools\n",
"\n",
"# Set up the Scan class to scan all checks for the provider\n",
"scan = Scan(provider=aws)\n",
"\n",
"# Parametrize the Scan to execute several checks, services, categories, compliances, etc.\n",
"scan_s3 = Scan(provider=aws, services=[\"s3\"], severities=[\"critical\", \"high\"])\n",
"# scan_critical = Scan(provider=aws, severities=[\"critical\"])\n",
"# scan_internet_exposed = Scan(provider=aws, categories=[\"internet-exposed\"])\n",
"\n",
"# Start the scan with the `scan` method. This returns a generator with findings and progress.\n",
"print(\"\\n##### Scanning AWS #####\")\n",
"all_findings = []\n",
"total_findings = 0\n",
"for progress, findings in scan_s3.scan():\n",
" all_findings.extend(findings)\n",
" total_findings += len(findings)\n",
" print(f\"- Scan Progress: {progress}\\n- # Findings: {total_findings}\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Process and Display Findings\n",
"Process the scan results and display detailed information about each finding."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Finding's Details:\")\n",
"for finding in all_findings:\n",
" print(f\"\"\"\n",
" - Check ID: {finding.metadata.CheckID}\n",
" - Status: {str(finding.status)}\n",
" - Status Extended: {finding.status_extended}\n",
" - Resource ID: {finding.resource_uid}\n",
" - Resource Metadata: {finding.resource_metadata}\n",
" \"\"\")\n",
"\n",
"# Retrieve all findings in one line\n",
"print(\"\\n##### Getting all findings in one line #####\")\n",
"scan_s3 = Scan(provider=aws, services=[\"s3\"], severities=[\"critical\"])\n",
"all_findings_one_line = list(itertools.chain.from_iterable(findings for _, findings in scan_s3.scan()))\n",
"print(f\"Total findings collected in one line: {len(all_findings_one_line)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Check Metatada\n",
"```plain\n",
"CheckMetadata(\n",
" Provider='aws'\n",
" CheckID='s3_bucket_policy_public_write_access'\n",
" CheckTitle='Check if S3 buckets have policies which allow WRITE access.'\n",
" CheckType=['IAM']\n",
" CheckAliases=[]\n",
" ServiceName='s3'\n",
" SubServiceName=''\n",
" ResourceIdTemplate='arn:partition:s3:::bucket_name'\n",
" Severity=<Severity.critical: 'critical'>\n",
" ResourceType='AwsS3Bucket'\n",
" Description='Check if S3 buckets have policies which allow WRITE access.'\n",
" Risk='Non intended users can put objects in a given bucket.'\n",
" RelatedUrl=''\n",
" Remediation=\n",
" Remediation(\n",
" Code=Code(\n",
" NativeIaC=''\n",
" Terraform=''\n",
" CLI=''\n",
" Other='https://docs.prowler.com/checks/aws/s3-policies/s3_18-write-permissions-public#aws-console')\n",
" Recommendation=Recommendation(Text='Ensure proper bucket policy is in place with the least privilege principle applied.'\n",
" Url='https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_s3_rw-bucket.html'\n",
" )\n",
" )\n",
" Categories=['internet-exposed']\n",
" DependsOn=[]\n",
" RelatedTo=[]\n",
" Notes=''\n",
" # Compliance framework: A list of requirement IDs where the check is present.\n",
" Compliance={\n",
" \"CIS-1.10\": [\"5.2.13\"],\n",
" \"CIS-1.8\": [\"5.2.13\"]\n",
" }\n",
")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Output Formats"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import necessary libraries for output\n",
"from prowler.lib.outputs.csv.csv import CSV\n",
"from prowler.lib.outputs.ocsf.ocsf import OCSF\n",
"from prowler.lib.outputs.asff.asff import ASFF # Only for AWS\n",
"from prowler.lib.outputs.html.html import HTML\n",
"from prowler.lib.outputs.outputs import extract_findings_statistics\n",
"import datetime\n",
"\n",
"# Get current date and time in YYYY-MM-DD_HH-MM-SS format for filenames\n",
"current_datetime = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\n",
"\n",
"# Write findings to CSV file\n",
"print(\"Writing findings to CSV file...\")\n",
"csv_filename = f\"./output/findings_{current_datetime}.csv\"\n",
"csv = CSV(findings=all_findings, create_file_descriptor=True, file_path=csv_filename)\n",
"csv.batch_write_data_to_file()\n",
"print(f\"Done! CSV File Path: {csv._file_descriptor.name}\")\n",
"\n",
"# Write findings to OCSF file\n",
"print(\"Writing findings to OCSF file...\")\n",
"ocsf_filename = f\"./output/findings_{current_datetime}.ocsf\"\n",
"ocsf = OCSF(findings=all_findings, create_file_descriptor=True, file_path=ocsf_filename)\n",
"ocsf.batch_write_data_to_file()\n",
"print(f\"Done! OCSF File Path: {ocsf._file_descriptor.name}\")\n",
"\n",
"# Write findings to ASFF file\n",
"print(\"Writing findings to ASFF file...\")\n",
"asff_filename = f\"./output/findings_{current_datetime}.asff\"\n",
"asff = ASFF(findings=all_findings, create_file_descriptor=True, file_path=asff_filename)\n",
"asff.batch_write_data_to_file()\n",
"print(f\"Done! ASFF File Path: {asff._file_descriptor.name}\")\n",
"\n",
"# Write findings to HTML file\n",
"print(\"Writing findings to HTML file...\")\n",
"html_filename = f\"./output/findings_{current_datetime}.html\"\n",
"stats = extract_findings_statistics(all_findings)\n",
"html = HTML(findings=all_findings, create_file_descriptor=True, file_path=html_filename)\n",
"html.batch_write_data_to_file(provider=aws, stats=stats)\n",
"print(f\"Done! HTML File Path: {html._file_descriptor.name}\")\n",
"\n",
"# IMPORTANT: The create_file_descriptor parameter will be removed in 5.4.0\n",
"# The file descriptor will be created by default when the Output class is instantiated"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Integrate with AWS S3\n",
"Send findings to AWS S3."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import the S3 class to send findings to AWS S3\n",
"from prowler.providers.aws.lib.s3.s3 import S3\n",
"\n",
"print(\"\\n##### Sending findings to S3 bucket #####\")\n",
"generated_outputs = {\"regular\": [csv, ocsf, asff, html], \"compliance\": []}\n",
"s3_integration = S3(aws.session.current_session, bucket_name=\"sdk-core\", output_directory=\"output\")\n",
"s3_integration.send_to_bucket(generated_outputs)\n",
"\n",
"# This upload the output files to the S3 bucket. In this case:\n",
"# sdk-core/output/csv/findings_2025-02-26_16-25-30.csv\n",
"# sdk-core/output/ocsf/findings_2025-02-26_16-25-30.ocsf\n",
"# sdk-core/output/asff/findings_2025-02-26_16-25-30.asff"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Integrate with AWS Security Hub\n",
"Send findings to AWS Security Hub for centralized security monitoring."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import the SecurityHub class to send findings to AWS Security Hub\n",
"from prowler.providers.aws.lib.security_hub.security_hub import SecurityHub\n",
"\n",
"# Print message indicating the start of the process\n",
"print(\"\\n##### Sending findings to AWS Security Hub #####\")\n",
"\n",
"# Get available AWS regions for Security Hub.\n",
"# Each finding can only be sent to Security Hub within its own region.\n",
"# Additionally, it verifies that Prowlers integration is active in\n",
"# Security Hub before sending\n",
"available_regions = aws.get_available_aws_service_regions(\n",
" \"securityhub\",\n",
" aws.identity.partition,\n",
" aws.identity.audited_regions,\n",
")\n",
"\n",
"# Initialize the SecurityHub class with necessary parameters\n",
"security_hub = SecurityHub(\n",
" aws_account_id=aws.identity.account,\n",
" aws_partition=aws.identity.partition,\n",
" aws_session=aws.session.current_session,\n",
" findings=asff.data,\n",
" send_only_fails=False,\n",
" aws_security_hub_available_regions=available_regions,\n",
")\n",
"\n",
"# Send findings to AWS Security Hub\n",
"findings_sent_to_security_hub = security_hub.batch_send_to_security_hub()\n",
"\n",
"# Print the number of findings sent to AWS Security Hub\n",
"print(f\"{findings_sent_to_security_hub} findings sent to AWS Security Hub!\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "prowler-HDV3a8VZ-py3.12",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}