{ "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=\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 Prowler’s 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 }