ScoutSuite Feuille de chaleur
Aperçu général
ScoutSuite est un outil d'audit de sécurité multi-cloud ouvert qui permet d'évaluer la posture de sécurité des environnements cloud. Il recueille des données de configuration pour une inspection manuelle et met en évidence les zones à risque. ScoutSuite prend en charge Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Alibaba Cloud et Oracle Cloud Infrastructure (OCI). L'outil produit des rapports HTML détaillés avec des constatations organisées par service et comprend des lignes directrices sur l'assainissement.
C'est-à-dire Caractéristiques principales: Support multicloud, contrôles de sécurité complets, rapports HTML détaillés, personnalisation des règles, cartographie de conformité, numérisation par API, et analyse de configuration étendue sur plus de 100 services.
Installation et configuration
Installation du paquet Python
# Install Python 3.7+ (required)
python3 --version
# Install ScoutSuite via pip
pip3 install scoutsuite
# Alternative: Install with all dependencies
pip3 install scoutsuite[all]
# Verify installation
scout --version
# Update ScoutSuite
pip3 install --upgrade scoutsuite
# Install specific version
pip3 install scoutsuite==5.13.0
# Install development version
pip3 install git+https://github.com/nccgroup/ScoutSuite.git
Installation Docker
# Pull ScoutSuite Docker image
docker pull nccgroup/scoutsuite:latest
# Run ScoutSuite in Docker
docker run --rm -it \
-v ~/.aws:/root/.aws \
-v ~/.azure:/root/.azure \
-v ~/.config/gcloud:/root/.config/gcloud \
-v $(pwd)/scoutsuite-results:/opt/scoutsuite/scoutsuite-results \
nccgroup/scoutsuite:latest \
aws
# Create Docker alias for easier usage
echo 'alias scoutsuite="docker run --rm -it -v ~/.aws:/root/.aws -v ~/.azure:/root/.azure -v ~/.config/gcloud:/root/.config/gcloud -v $(pwd)/scoutsuite-results:/opt/scoutsuite/scoutsuite-results nccgroup/scoutsuite:latest"' >> ~/.bashrc
source ~/.bashrc
# Create Docker Compose file
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
scoutsuite:
image: nccgroup/scoutsuite:latest
volumes:
- ~/.aws:/root/.aws
- ~/.azure:/root/.azure
- ~/.config/gcloud:/root/.config/gcloud
- ./scoutsuite-results:/opt/scoutsuite/scoutsuite-results
environment:
- AWS_PROFILE=default
- AZURE_SUBSCRIPTION_ID=${AZURE_SUBSCRIPTION_ID}
- GOOGLE_APPLICATION_CREDENTIALS=/root/.config/gcloud/application_default_credentials.json
EOF
# Run with Docker Compose
docker-compose run scoutsuite aws
```_
### Installation de la source
```bash
# Clone ScoutSuite repository
git clone https://github.com/nccgroup/ScoutSuite.git
cd ScoutSuite
# Install dependencies
pip3 install -r requirements.txt
# Install in development mode
pip3 install -e .
# Verify installation
python3 -m ScoutSuite --version
# Create symbolic link
sudo ln -sf $(pwd)/scout.py /usr/local/bin/scout
# Set up virtual environment (recommended)
python3 -m venv scoutsuite-env
source scoutsuite-env/bin/activate
pip3 install -r requirements.txt
pip3 install -e .
```_
## Configuration du fournisseur de cloud
### Configuration AWS
```bash
# Install AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Configure AWS credentials
aws configure
# Enter: Access Key ID, Secret Access Key, Region, Output format
# Alternative: Use environment variables
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"
# Alternative: Use IAM roles (recommended for EC2)
# Attach IAM role with required permissions to EC2 instance
# Test AWS configuration
aws sts get-caller-identity
# Configure multiple profiles
aws configure --profile production
aws configure --profile development
aws configure --profile staging
# List configured profiles
aws configure list-profiles
# Set default profile
export AWS_PROFILE=production
# Required AWS permissions for ScoutSuite
cat > scoutsuite-aws-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"access-analyzer:List*",
"account:Get*",
"acm:Describe*",
"acm:List*",
"apigateway:GET",
"application-autoscaling:Describe*",
"autoscaling:Describe*",
"backup:List*",
"cloudformation:Describe*",
"cloudformation:Get*",
"cloudformation:List*",
"cloudfront:Get*",
"cloudfront:List*",
"cloudtrail:Describe*",
"cloudtrail:Get*",
"cloudtrail:List*",
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"config:Describe*",
"config:Get*",
"config:List*",
"directconnect:Describe*",
"dms:Describe*",
"dms:List*",
"ds:Describe*",
"ds:Get*",
"ds:List*",
"dynamodb:Describe*",
"dynamodb:List*",
"ec2:Describe*",
"ec2:Get*",
"ecr:Describe*",
"ecr:Get*",
"ecr:List*",
"ecs:Describe*",
"ecs:List*",
"efs:Describe*",
"eks:Describe*",
"eks:List*",
"elasticache:Describe*",
"elasticbeanstalk:Describe*",
"elasticfilesystem:Describe*",
"elasticloadbalancing:Describe*",
"elasticmapreduce:Describe*",
"elasticmapreduce:List*",
"es:Describe*",
"es:List*",
"events:Describe*",
"events:List*",
"firehose:Describe*",
"firehose:List*",
"guardduty:Get*",
"guardduty:List*",
"iam:Generate*",
"iam:Get*",
"iam:List*",
"iam:Simulate*",
"inspector:Describe*",
"inspector:Get*",
"inspector:List*",
"kinesis:Describe*",
"kinesis:List*",
"kms:Describe*",
"kms:Get*",
"kms:List*",
"lambda:Get*",
"lambda:List*",
"logs:Describe*",
"logs:Get*",
"logs:List*",
"organizations:Describe*",
"organizations:List*",
"rds:Describe*",
"rds:List*",
"redshift:Describe*",
"route53:Get*",
"route53:List*",
"route53domains:Get*",
"route53domains:List*",
"s3:Get*",
"s3:List*",
"secretsmanager:Describe*",
"secretsmanager:Get*",
"secretsmanager:List*",
"securityhub:Describe*",
"securityhub:Get*",
"securityhub:List*",
"ses:Get*",
"ses:List*",
"shield:Describe*",
"shield:Get*",
"shield:List*",
"sns:Get*",
"sns:List*",
"sqs:Get*",
"sqs:List*",
"ssm:Describe*",
"ssm:Get*",
"ssm:List*",
"support:Describe*",
"trustedadvisor:Describe*",
"waf:Get*",
"waf:List*",
"wafv2:Get*",
"wafv2:List*"
],
"Resource": "*"
}
]
}
EOF
# Create IAM policy
aws iam create-policy \
--policy-name ScoutSuitePolicy \
--policy-document file://scoutsuite-aws-policy.json
# Attach policy to user
aws iam attach-user-policy \
--user-name your-username \
--policy-arn arn:aws:iam::ACCOUNT-ID:policy/ScoutSuitePolicy
Configuration d'azur
# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Login to Azure
az login
# List subscriptions
az account list --output table
# Set default subscription
az account set --subscription "subscription-id"
# Create service principal for ScoutSuite
az ad sp create-for-rbac \
--name "ScoutSuite" \
--role "Reader" \
--scopes "/subscriptions/subscription-id"
# Alternative: Use environment variables
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"
export AZURE_TENANT_ID="your-tenant-id"
export AZURE_SUBSCRIPTION_ID="your-subscription-id"
# Test Azure configuration
az account show
# Required Azure permissions for ScoutSuite
# Reader role is sufficient for most checks
# Additional permissions may be needed for specific services
# Create custom role for ScoutSuite (optional)
cat > scoutsuite-azure-role.json << 'EOF'
{
"Name": "ScoutSuite Reader",
"Description": "Custom role for ScoutSuite security scanning",
"Actions": [
"*/read",
"Microsoft.Authorization/*/read",
"Microsoft.Security/*/read",
"Microsoft.PolicyInsights/*/read"
],
"NotActions": [],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/subscription-id"
]
}
EOF
# Create custom role
az role definition create --role-definition scoutsuite-azure-role.json
# Assign custom role to service principal
az role assignment create \
--assignee "service-principal-id" \
--role "ScoutSuite Reader" \
--scope "/subscriptions/subscription-id"
Configuration de la plateforme Google Cloud
# Install Google Cloud SDK
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
# Initialize gcloud
gcloud init
# Login to GCP
gcloud auth login
# Set default project
gcloud config set project your-project-id
# List projects
gcloud projects list
# Create service account for ScoutSuite
gcloud iam service-accounts create scoutsuite \
--display-name="ScoutSuite Service Account" \
--description="Service account for ScoutSuite security scanning"
# Grant required roles to service account
gcloud projects add-iam-policy-binding your-project-id \
--member="serviceAccount:scoutsuite@your-project-id.iam.gserviceaccount.com" \
--role="roles/viewer"
gcloud projects add-iam-policy-binding your-project-id \
--member="serviceAccount:scoutsuite@your-project-id.iam.gserviceaccount.com" \
--role="roles/security.securityReviewer"
gcloud projects add-iam-policy-binding your-project-id \
--member="serviceAccount:scoutsuite@your-project-id.iam.gserviceaccount.com" \
--role="roles/cloudsql.viewer"
# Create and download service account key
gcloud iam service-accounts keys create scoutsuite-key.json \
--iam-account=scoutsuite@your-project-id.iam.gserviceaccount.com
# Set environment variable for authentication
export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/scoutsuite-key.json"
# Alternative: Use application default credentials
gcloud auth application-default login
# Test GCP configuration
gcloud auth list
gcloud config list
# Enable required APIs
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable iam.googleapis.com
gcloud services enable compute.googleapis.com
gcloud services enable storage.googleapis.com
gcloud services enable sqladmin.googleapis.com
gcloud services enable container.googleapis.com
Utilisation et numérisation de base
Analyse AWS
# Basic AWS scan
scout aws
# Scan with specific profile
scout aws --profile production
# Scan specific regions
scout aws --regions us-east-1
scout aws --regions us-east-1,us-west-2,eu-west-1
# Scan all regions
scout aws --all-regions
# Scan with custom report name
scout aws --report-name "aws-security-audit-2024"
# Scan with custom output directory
scout aws --report-dir ./security-reports
# Scan specific services
scout aws --services s3
scout aws --services s3,ec2,iam
# List available services
scout aws --list-services
# Scan with custom rules
scout aws --ruleset-name custom-rules
# Scan with excluded rules
scout aws --skip-rules s3-bucket-world-readable
# Scan with custom filters
scout aws --filters filters.json
# Scan with debug output
scout aws --debug
# Scan with quiet mode
scout aws --quiet
# Scan with no browser (headless)
scout aws --no-browser
# Scan with custom thread count
scout aws --max-workers 10
# Scan with timeout
scout aws --timeout 3600
Numérisation d'azur
# Basic Azure scan
scout azure
# Scan with specific subscription
scout azure --subscription-id "subscription-id"
# Scan with service principal
scout azure \
--client-id "client-id" \
--client-secret "client-secret" \
--tenant-id "tenant-id"
# Scan with custom report name
scout azure --report-name "azure-security-audit-2024"
# Scan specific services
scout azure --services keyvault
scout azure --services keyvault,storage,network
# List available services
scout azure --list-services
# Scan with custom rules
scout azure --ruleset-name custom-azure-rules
# Scan with excluded rules
scout azure --skip-rules storage-account-https-only
# Scan all subscriptions (if permissions allow)
scout azure --all-subscriptions
# Scan with debug output
scout azure --debug
# Scan with custom output directory
scout azure --report-dir ./azure-reports
# Scan with no browser
scout azure --no-browser
Scannage de la plateforme Google Cloud
# Basic GCP scan
scout gcp
# Scan with specific project
scout gcp --project-id "your-project-id"
# Scan with service account key
scout gcp --service-account-key-file scoutsuite-key.json
# Scan with custom report name
scout gcp --report-name "gcp-security-audit-2024"
# Scan specific services
scout gcp --services compute
scout gcp --services compute,storage,iam
# List available services
scout gcp --list-services
# Scan with custom rules
scout gcp --ruleset-name custom-gcp-rules
# Scan with excluded rules
scout gcp --skip-rules compute-instance-public-ip
# Scan all projects (if permissions allow)
scout gcp --all-projects
# Scan with debug output
scout gcp --debug
# Scan with custom output directory
scout gcp --report-dir ./gcp-reports
# Scan with no browser
scout gcp --no-browser
# Scan with custom folder/organization
scout gcp --folder-id "folder-id"
scout gcp --organization-id "organization-id"
Numérisation multi-cloud
# Scan multiple cloud providers sequentially
scout aws --report-name "multi-cloud-aws"
scout azure --report-name "multi-cloud-azure"
scout gcp --report-name "multi-cloud-gcp"
# Create multi-cloud scanning script
cat > multi_cloud_scan.sh << 'EOF'
#!/bin/bash
# Multi-cloud ScoutSuite scanning
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
REPORT_DIR="multi_cloud_scan_$TIMESTAMP"
mkdir -p "$REPORT_DIR"
echo "Starting multi-cloud security scan..."
# AWS scan
echo "Scanning AWS..."
scout aws \
--report-name "aws_scan_$TIMESTAMP" \
--report-dir "$REPORT_DIR" \
--no-browser \
--quiet
# Azure scan
echo "Scanning Azure..."
scout azure \
--report-name "azure_scan_$TIMESTAMP" \
--report-dir "$REPORT_DIR" \
--no-browser \
--quiet
# GCP scan
echo "Scanning GCP..."
scout gcp \
--report-name "gcp_scan_$TIMESTAMP" \
--report-dir "$REPORT_DIR" \
--no-browser \
--quiet
echo "Multi-cloud scan completed. Reports in: $REPORT_DIR"
# Generate summary
python3 << 'PYTHON'
import json
import glob
import os
def generate_multi_cloud_summary(report_dir):
summary = {
"timestamp": "$TIMESTAMP",
"providers": {},
"total_findings": 0,
"critical_findings": 0,
"high_findings": 0
}
# Process each provider's results
for provider in ["aws", "azure", "gcp"]:
provider_file = f"{report_dir}/{provider}_scan_$TIMESTAMP.js"
if os.path.exists(provider_file):
try:
# ScoutSuite generates JavaScript files, need to extract JSON
with open(provider_file, 'r') as f:
content = f.read()
# Extract JSON data from JavaScript
start_marker = "scoutsuite_results = "
end_marker = ";"
start_idx = content.find(start_marker)
if start_idx != -1:
start_idx += len(start_marker)
end_idx = content.rfind(end_marker)
if end_idx != -1:
json_str = content[start_idx:end_idx]
data = json.loads(json_str)
# Count findings
findings = 0
critical = 0
high = 0
# Navigate through ScoutSuite data structure
if 'services' in data:
for service_name, service_data in data['services'].items():
if 'findings' in service_data:
for finding_key, finding_data in service_data['findings'].items():
if 'items' in finding_data:
finding_count = len(finding_data['items'])
findings += finding_count
# Categorize by severity
level = finding_data.get('level', 'unknown')
if level == 'danger':
critical += finding_count
elif level == 'warning':
high += finding_count
summary["providers"][provider] = {
"findings": findings,
"critical": critical,
"high": high
}
summary["total_findings"] += findings
summary["critical_findings"] += critical
summary["high_findings"] += high
except Exception as e:
print(f"Error processing {provider} results: {e}")
summary["providers"][provider] = {"error": str(e)}
# Save summary
with open(f"{report_dir}/multi_cloud_summary.json", 'w') as f:
json.dump(summary, f, indent=2)
print(f"Multi-cloud summary generated: {report_dir}/multi_cloud_summary.json")
print(f"Total findings across all providers: {summary['total_findings']}")
print(f"Critical findings: {summary['critical_findings']}")
print(f"High findings: {summary['high_findings']}")
generate_multi_cloud_summary("$REPORT_DIR")
PYTHON
EOF
chmod +x multi_cloud_scan.sh
./multi_cloud_scan.sh
Configuration et personnalisation avancées
Règles et ensembles de règles sur mesure
#!/usr/bin/env python3
# Custom ScoutSuite rules
"""
Custom rule example: Check for S3 buckets with public read access
"""
import json
from ScoutSuite.core.console import print_exception
from ScoutSuite.providers.aws.facade.base import AWSFacade
from ScoutSuite.providers.aws.resources.base import AWSResources
class S3BucketPublicReadRule:
"""Custom rule to check for S3 buckets with public read access"""
def __init__(self):
self.rule_name = "s3-bucket-public-read-custom"
self.rule_description = "S3 bucket allows public read access"
self.rule_level = "danger" # danger, warning, info
self.rule_path = "s3.buckets.id.bucket_policy"
def check_bucket_policy(self, bucket_policy):
"""Check if bucket policy allows public read access"""
if not bucket_policy:
return False
try:
policy = json.loads(bucket_policy)
for statement in policy.get('Statement', []):
# Check for public read permissions
if (statement.get('Effect') == 'Allow' and
statement.get('Principal') == '*' and
any(action in ['s3:GetObject', 's3:GetObjectVersion', 's3:*']
for action in statement.get('Action', []))):
return True
except (json.JSONDecodeError, TypeError):
pass
return False
def run(self, aws_config):
"""Run the custom rule against AWS configuration"""
findings = []
for region_name, region_data in aws_config['services']['s3']['regions'].items():
for bucket_name, bucket_data in region_data.get('buckets', {}).items():
bucket_policy = bucket_data.get('bucket_policy')
if self.check_bucket_policy(bucket_policy):
findings.append({
'bucket_name': bucket_name,
'region': region_name,
'description': f"Bucket {bucket_name} allows public read access",
'risk': "High",
'remediation': "Review and restrict bucket policy to prevent public access"
})
return findings
# Custom ruleset configuration
custom_ruleset = {
"about": "Custom ScoutSuite ruleset for enhanced security checks",
"rules": {
"s3-bucket-public-read-custom": {
"description": "S3 bucket allows public read access",
"path": "s3.buckets.id.bucket_policy",
"conditions": [
"and",
[
"s3.buckets.id.bucket_policy",
"containsString",
"\"Principal\": \"*\""
],
[
"s3.buckets.id.bucket_policy",
"containsString",
"s3:GetObject"
]
],
"level": "danger"
},
"ec2-instance-public-ip-custom": {
"description": "EC2 instance has public IP address",
"path": "ec2.regions.id.vpcs.id.instances.id.public_ip_address",
"conditions": [
"ec2.regions.id.vpcs.id.instances.id.public_ip_address",
"notNull",
""
],
"level": "warning"
},
"iam-user-no-mfa-custom": {
"description": "IAM user does not have MFA enabled",
"path": "iam.users.id.mfa_devices",
"conditions": [
"iam.users.id.mfa_devices",
"empty",
""
],
"level": "warning"
},
"rds-instance-public-custom": {
"description": "RDS instance is publicly accessible",
"path": "rds.regions.id.vpcs.id.instances.id.publicly_accessible",
"conditions": [
"rds.regions.id.vpcs.id.instances.id.publicly_accessible",
"true",
""
],
"level": "danger"
},
"cloudtrail-not-encrypted-custom": {
"description": "CloudTrail is not encrypted with KMS",
"path": "cloudtrail.regions.id.trails.id.kms_key_id",
"conditions": [
"cloudtrail.regions.id.trails.id.kms_key_id",
"null",
""
],
"level": "warning"
}
}
}
# Save custom ruleset
with open('custom_ruleset.json', 'w') as f:
json.dump(custom_ruleset, f, indent=2)
print("Custom ruleset created: custom_ruleset.json")
Filtre avancé et configuration
{
"filters": {
"description": "Custom filters for ScoutSuite scanning",
"filters": [
{
"description": "Exclude test environments",
"path": "*.*.*.*.tags.Environment",
"operator": "notEqual",
"value": "test"
},
{
"description": "Include only production resources",
"path": "*.*.*.*.tags.Environment",
"operator": "equal",
"value": "production"
},
{
"description": "Exclude specific S3 buckets",
"path": "s3.buckets.*.name",
"operator": "notIn",
"value": ["test-bucket", "dev-bucket", "temp-bucket"]
},
{
"description": "Include only specific regions",
"path": "*.regions.*",
"operator": "in",
"value": ["us-east-1", "us-west-2", "eu-west-1"]
},
{
"description": "Exclude terminated EC2 instances",
"path": "ec2.regions.*.vpcs.*.instances.*.state",
"operator": "notEqual",
"value": "terminated"
}
]
}
}
Modèles de rapports personnalisés
<!-- custom_report_template.html -->
<!DOCTYPE html>
<html>
<head>
<title>Custom ScoutSuite Security Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background: #2c3e50; color: white; padding: 20px; border-radius: 5px; }
.summary { background: #ecf0f1; padding: 20px; margin: 20px 0; border-radius: 5px; }
.finding { border-left: 4px solid; padding: 15px; margin: 10px 0; }
.danger { border-left-color: #e74c3c; background: #fadbd8; }
.warning { border-left-color: #f39c12; background: #fdeaa7; }
.info { border-left-color: #3498db; background: #d6eaf8; }
.service-section { margin: 30px 0; }
.service-title { background: #34495e; color: white; padding: 10px; }
table { border-collapse: collapse; width: 100%; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
th { background-color: #34495e; color: white; }
</style>
</head>
<body>
<div class="header">
<h1>🔒 Custom Security Assessment Report</h1>
<p>Generated by ScoutSuite on: {{ timestamp }}</p>
<p>Cloud Provider: {{ provider }}</p>
<p>Account/Subscription: {{ account_id }}</p>
</div>
<div class="summary">
<h2>Executive Summary</h2>
<table>
<tr><th>Metric</th><th>Count</th></tr>
<tr><td>Total Findings</td><td>{{ total_findings }}</td></tr>
<tr><td>Critical (Danger)</td><td style="color: #e74c3c;">{{ danger_count }}</td></tr>
<tr><td>High (Warning)</td><td style="color: #f39c12;">{{ warning_count }}</td></tr>
<tr><td>Info</td><td style="color: #3498db;">{{ info_count }}</td></tr>
</table>
</div>
{% for service_name, service_data in services.items() %}
<div class="service-section">
<div class="service-title">
<h2>{{ service_name.upper() }} Service</h2>
</div>
{% for finding_name, finding_data in service_data.findings.items() %}
<div class="finding {{ finding_data.level }}">
<h3>{{ finding_data.description }}</h3>
<p><strong>Severity:</strong> {{ finding_data.level.title() }}</p>
<p><strong>Affected Resources:</strong> {{ finding_data.items|length }}</p>
{% if finding_data.items %}
<details>
<summary>Show affected resources ({{ finding_data.items|length }})</summary>
<ul>
{% for item in finding_data.items[:10] %}
<li>{{ item }}</li>
{% endfor %}
{% if finding_data.items|length > 10 %}
<li>... and {{ finding_data.items|length - 10 }} more</li>
{% endif %}
</ul>
</details>
{% endif %}
</div>
{% endfor %}
</div>
{% endfor %}
<div class="summary">
<h2>Recommendations</h2>
<ol>
<li>Address all critical (danger) findings immediately</li>
<li>Review and remediate high (warning) findings</li>
<li>Implement security monitoring and alerting</li>
<li>Regular security assessments with ScoutSuite</li>
<li>Follow cloud provider security best practices</li>
</ol>
</div>
</body>
</html>
Analyse et automatisation des rapports
Traitement et analyse des rapports
#!/usr/bin/env python3
# ScoutSuite report analysis and processing
import json
import re
import os
import glob
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
class ScoutSuiteAnalyzer:
"""Advanced analysis for ScoutSuite reports"""
def __init__(self):
self.timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
def extract_data_from_js(self, js_file_path):
"""Extract JSON data from ScoutSuite JavaScript report file"""
try:
with open(js_file_path, 'r') as f:
content = f.read()
# Extract JSON data from JavaScript
start_marker = "scoutsuite_results = "
end_marker = ";"
start_idx = content.find(start_marker)
if start_idx != -1:
start_idx += len(start_marker)
end_idx = content.rfind(end_marker)
if end_idx != -1:
json_str = content[start_idx:end_idx]
return json.loads(json_str)
except Exception as e:
print(f"Error extracting data from {js_file_path}: {e}")
return None
def analyze_findings(self, scoutsuite_data):
"""Analyze ScoutSuite findings and generate statistics"""
analysis = {
'total_findings': 0,
'severity_breakdown': {'danger': 0, 'warning': 0, 'info': 0},
'service_breakdown': {},
'top_findings': [],
'compliance_issues': [],
'remediation_priorities': []
}
if 'services' not in scoutsuite_data:
return analysis
for service_name, service_data in scoutsuite_data['services'].items():
if 'findings' not in service_data:
continue
service_findings = 0
service_critical = 0
for finding_key, finding_data in service_data['findings'].items():
if 'items' not in finding_data:
continue
finding_count = len(finding_data['items'])
service_findings += finding_count
analysis['total_findings'] += finding_count
# Count by severity
level = finding_data.get('level', 'info')
if level in analysis['severity_breakdown']:
analysis['severity_breakdown'][level] += finding_count
if level == 'danger':
service_critical += finding_count
# Collect top findings
if finding_count > 0:
analysis['top_findings'].append({
'service': service_name,
'finding': finding_data.get('description', finding_key),
'count': finding_count,
'severity': level,
'items': finding_data['items'][:5] # Sample items
})
# Service breakdown
analysis['service_breakdown'][service_name] = {
'total_findings': service_findings,
'critical_findings': service_critical
}
# Sort top findings by severity and count
severity_order = {'danger': 3, 'warning': 2, 'info': 1}
analysis['top_findings'].sort(
key=lambda x: (severity_order.get(x['severity'], 0), x['count']),
reverse=True
)
# Generate remediation priorities
analysis['remediation_priorities'] = self._generate_remediation_priorities(analysis)
return analysis
def _generate_remediation_priorities(self, analysis):
"""Generate remediation priorities based on findings"""
priorities = []
# Critical findings first
critical_count = analysis['severity_breakdown']['danger']
if critical_count > 0:
priorities.append({
'priority': 'IMMEDIATE',
'title': 'Address Critical Security Issues',
'description': f"Immediately remediate {critical_count} critical security findings",
'timeline': '24-48 hours'
})
# High-impact services
for service, stats in analysis['service_breakdown'].items():
if stats['critical_findings'] > 5:
priorities.append({
'priority': 'HIGH',
'title': f'Secure {service.upper()} Service',
'description': f"Address {stats['critical_findings']} critical issues in {service}",
'timeline': '1 week'
})
# Warning-level issues
warning_count = analysis['severity_breakdown']['warning']
if warning_count > 10:
priorities.append({
'priority': 'MEDIUM',
'title': 'Reduce Warning-Level Findings',
'description': f"Address {warning_count} warning-level security findings",
'timeline': '2-4 weeks'
})
return priorities[:5] # Top 5 priorities
def generate_executive_report(self, analysis, provider, account_id):
"""Generate executive summary report"""
total_findings = analysis['total_findings']
critical_findings = analysis['severity_breakdown']['danger']
# Calculate risk score
risk_score = self._calculate_risk_score(analysis)
executive_summary = {
'provider': provider,
'account_id': account_id,
'scan_date': self.timestamp,
'total_findings': total_findings,
'critical_findings': critical_findings,
'risk_score': risk_score,
'risk_level': self._get_risk_level(risk_score),
'top_services_at_risk': self._get_top_services_at_risk(analysis['service_breakdown']),
'remediation_priorities': analysis['remediation_priorities'],
'compliance_status': self._assess_compliance_status(analysis)
}
return executive_summary
def _calculate_risk_score(self, analysis):
"""Calculate overall risk score (0-100)"""
total = analysis['total_findings']
if total == 0:
return 0
# Weight by severity
critical_weight = 10
warning_weight = 3
info_weight = 1
weighted_score = (
analysis['severity_breakdown']['danger'] * critical_weight +
analysis['severity_breakdown']['warning'] * warning_weight +
analysis['severity_breakdown']['info'] * info_weight
)
# Normalize to 0-100 scale
max_possible_score = total * critical_weight
risk_score = (weighted_score / max_possible_score * 100) if max_possible_score > 0 else 0
return min(100, round(risk_score, 1))
def _get_risk_level(self, risk_score):
"""Determine risk level based on score"""
if risk_score >= 80:
return "CRITICAL"
elif risk_score >= 60:
return "HIGH"
elif risk_score >= 40:
return "MEDIUM"
elif risk_score >= 20:
return "LOW"
else:
return "MINIMAL"
def _get_top_services_at_risk(self, service_breakdown):
"""Get services with highest risk"""
services_at_risk = []
for service, stats in service_breakdown.items():
if stats['total_findings'] > 0:
risk_ratio = stats['critical_findings'] / stats['total_findings']
services_at_risk.append({
'service': service,
'total_findings': stats['total_findings'],
'critical_findings': stats['critical_findings'],
'risk_ratio': round(risk_ratio, 2)
})
return sorted(services_at_risk, key=lambda x: x['risk_ratio'], reverse=True)[:5]
def _assess_compliance_status(self, analysis):
"""Assess compliance status based on findings"""
critical_count = analysis['severity_breakdown']['danger']
warning_count = analysis['severity_breakdown']['warning']
if critical_count == 0 and warning_count <= 5:
return "COMPLIANT"
elif critical_count <= 2 and warning_count <= 15:
return "MOSTLY_COMPLIANT"
elif critical_count <= 5:
return "NON_COMPLIANT"
else:
return "SEVERELY_NON_COMPLIANT"
def generate_charts(self, analysis, output_dir):
"""Generate charts and visualizations"""
os.makedirs(output_dir, exist_ok=True)
# Set style
plt.style.use('seaborn-v0_8')
# Create figure with subplots
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
# 1. Severity breakdown pie chart
severity_data = {k: v for k, v in analysis['severity_breakdown'].items() if v > 0}
if severity_data:
colors = ['#e74c3c', '#f39c12', '#3498db']
axes[0, 0].pie(severity_data.values(), labels=severity_data.keys(),
autopct='%1.1f%%', colors=colors)
axes[0, 0].set_title('Findings by Severity')
# 2. Service breakdown bar chart
services = list(analysis['service_breakdown'].keys())[:10]
service_counts = [analysis['service_breakdown'][s]['total_findings'] for s in services]
axes[0, 1].barh(services, service_counts, color='#e74c3c')
axes[0, 1].set_title('Findings by Service')
axes[0, 1].set_xlabel('Number of Findings')
# 3. Critical findings by service
critical_counts = [analysis['service_breakdown'][s]['critical_findings'] for s in services]
axes[0, 2].bar(services, critical_counts, color='#c0392b')
axes[0, 2].set_title('Critical Findings by Service')
axes[0, 2].set_ylabel('Critical Findings')
axes[0, 2].tick_params(axis='x', rotation=45)
# 4. Top findings
top_findings = analysis['top_findings'][:10]
finding_names = [f['finding'][:30] + '...' if len(f['finding']) > 30 else f['finding']
for f in top_findings]
finding_counts = [f['count'] for f in top_findings]
axes[1, 0].barh(finding_names, finding_counts, color='#f39c12')
axes[1, 0].set_title('Top 10 Findings')
axes[1, 0].set_xlabel('Count')
# 5. Risk distribution
risk_levels = ['Critical', 'Warning', 'Info']
risk_counts = [analysis['severity_breakdown']['danger'],
analysis['severity_breakdown']['warning'],
analysis['severity_breakdown']['info']]
axes[1, 1].bar(risk_levels, risk_counts, color=['#e74c3c', '#f39c12', '#3498db'])
axes[1, 1].set_title('Risk Distribution')
axes[1, 1].set_ylabel('Number of Findings')
# 6. Compliance trend (placeholder)
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
compliance_scores = [65, 70, 75, 80, 85, 90] # Example data
axes[1, 2].plot(months, compliance_scores, marker='o', color='#27ae60')
axes[1, 2].set_title('Compliance Score Trend')
axes[1, 2].set_ylabel('Compliance Score (%)')
axes[1, 2].set_ylim(0, 100)
plt.tight_layout()
chart_file = f"{output_dir}/scoutsuite_analysis_{self.timestamp}.png"
plt.savefig(chart_file, dpi=300, bbox_inches='tight')
plt.close()
print(f"Charts generated: {chart_file}")
return chart_file
def process_report(self, report_file, provider, account_id, output_dir):
"""Process ScoutSuite report and generate analysis"""
# Extract data from JavaScript report
scoutsuite_data = self.extract_data_from_js(report_file)
if not scoutsuite_data:
print(f"Failed to extract data from {report_file}")
return None
# Analyze findings
analysis = self.analyze_findings(scoutsuite_data)
# Generate executive report
executive_summary = self.generate_executive_report(analysis, provider, account_id)
# Create output directory
os.makedirs(output_dir, exist_ok=True)
# Save analysis results
analysis_file = f"{output_dir}/scoutsuite_analysis_{self.timestamp}.json"
with open(analysis_file, 'w') as f:
json.dump({
'executive_summary': executive_summary,
'detailed_analysis': analysis
}, f, indent=2)
# Generate charts
chart_file = self.generate_charts(analysis, output_dir)
# Generate CSV report
csv_file = self._generate_csv_report(analysis, output_dir)
print(f"Analysis completed:")
print(f" - Analysis file: {analysis_file}")
print(f" - Charts: {chart_file}")
print(f" - CSV report: {csv_file}")
return {
'analysis_file': analysis_file,
'chart_file': chart_file,
'csv_file': csv_file,
'executive_summary': executive_summary
}
def _generate_csv_report(self, analysis, output_dir):
"""Generate CSV report of findings"""
findings_data = []
for finding in analysis['top_findings']:
findings_data.append({
'Service': finding['service'],
'Finding': finding['finding'],
'Severity': finding['severity'],
'Count': finding['count'],
'Sample_Resources': ', '.join(finding['items'][:3])
})
df = pd.DataFrame(findings_data)
csv_file = f"{output_dir}/scoutsuite_findings_{self.timestamp}.csv"
df.to_csv(csv_file, index=False)
return csv_file
def main():
"""Main function for ScoutSuite analysis"""
import argparse
parser = argparse.ArgumentParser(description='ScoutSuite Report Analyzer')
parser.add_argument('report_file', help='ScoutSuite JavaScript report file')
parser.add_argument('--provider', default='aws', help='Cloud provider (aws, azure, gcp)')
parser.add_argument('--account-id', default='unknown', help='Account/Subscription ID')
parser.add_argument('--output-dir', default='analysis_results', help='Output directory')
args = parser.parse_args()
analyzer = ScoutSuiteAnalyzer()
results = analyzer.process_report(
args.report_file,
args.provider,
args.account_id,
args.output_dir
)
if results:
print("\nExecutive Summary:")
summary = results['executive_summary']
print(f"Risk Level: {summary['risk_level']}")
print(f"Risk Score: {summary['risk_score']}/100")
print(f"Total Findings: {summary['total_findings']}")
print(f"Critical Findings: {summary['critical_findings']}")
print(f"Compliance Status: {summary['compliance_status']}")
if __name__ == "__main__":
main()
Intégration et automatisation CI/CD
Intégration des actions GitHub
# .github/workflows/scoutsuite-security-scan.yml
name: ScoutSuite Multi-Cloud Security Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
# Run daily at 3 AM UTC
- cron: '0 3 * * *'
workflow_dispatch:
inputs:
cloud_provider:
description: 'Cloud provider to scan'
required: false
default: 'all'
type: choice
options:
- all
- aws
- azure
- gcp
jobs:
scoutsuite-scan:
runs-on: ubuntu-latest
strategy:
matrix:
provider: [aws, azure, gcp]
include:
- provider: aws
setup_script: setup_aws.sh
- provider: azure
setup_script: setup_azure.sh
- provider: gcp
setup_script: setup_gcp.sh
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install ScoutSuite
run: |
pip install scoutsuite
scout --version
- name: Setup AWS credentials
if: matrix.provider == 'aws'
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Setup Azure credentials
if: matrix.provider == 'azure'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Setup GCP credentials
if: matrix.provider == 'gcp'
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Run ScoutSuite scan
run: |
mkdir -p scoutsuite-results
# Skip if provider not selected in manual trigger
if [ "${{ github.event.inputs.cloud_provider }}" != "all" ] && [ "${{ github.event.inputs.cloud_provider }}" != "${{ matrix.provider }}" ]; then
echo "Skipping ${{ matrix.provider }} scan"
exit 0
fi
# Run scan based on provider
case "${{ matrix.provider }}" in
aws)
scout aws \
--report-name "aws_security_scan_$(date +%Y%m%d_%H%M%S)" \
--report-dir scoutsuite-results \
--no-browser \
--max-workers 5
;;
azure)
scout azure \
--report-name "azure_security_scan_$(date +%Y%m%d_%H%M%S)" \
--report-dir scoutsuite-results \
--no-browser \
--max-workers 5
;;
gcp)
scout gcp \
--report-name "gcp_security_scan_$(date +%Y%m%d_%H%M%S)" \
--report-dir scoutsuite-results \
--no-browser \
--max-workers 5
;;
esac
- name: Analyze results
run: |
pip install pandas matplotlib seaborn
# Find the latest report file
REPORT_FILE=$(find scoutsuite-results -name "*.js" -type f | head -1)
if [ -n "$REPORT_FILE" ]; then
python scripts/scoutsuite_analyzer.py "$REPORT_FILE" \
--provider "${{ matrix.provider }}" \
--account-id "github-actions" \
--output-dir scoutsuite-results
fi
- name: Security gate check
run: |
python << 'EOF'
import json
import sys
import glob
# Find analysis file
analysis_files = glob.glob('scoutsuite-results/scoutsuite_analysis_*.json')
if not analysis_files:
print("No analysis file found")
sys.exit(0)
with open(analysis_files[0], 'r') as f:
data = json.load(f)
executive_summary = data['executive_summary']
critical_findings = executive_summary['critical_findings']
risk_level = executive_summary['risk_level']
print(f"Security Assessment Results for ${{ matrix.provider }}:")
print(f"Critical findings: {critical_findings}")
print(f"Risk level: {risk_level}")
# Security gate logic
if risk_level in ['CRITICAL'] and critical_findings > 5:
print("❌ CRITICAL SECURITY ISSUES FOUND!")
print("Build failed due to critical security issues.")
sys.exit(1)
if risk_level in ['HIGH'] and critical_findings > 10:
print("⚠️ WARNING: High number of critical issues found!")
sys.exit(1)
print("✅ Security gate passed")
EOF
- name: Upload scan results
uses: actions/upload-artifact@v3
with:
name: scoutsuite-results-${{ matrix.provider }}
path: scoutsuite-results/
- name: Comment PR with results
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const glob = require('glob');
// Find analysis file
const analysisFiles = glob.sync('scoutsuite-results/scoutsuite_analysis_*.json');
if (analysisFiles.length === 0) {
console.log('No analysis file found');
return;
}
const data = JSON.parse(fs.readFileSync(analysisFiles[0], 'utf8'));
const summary = data.executive_summary;
const comment = `## 🔒 ScoutSuite Security Scan Results (${{ matrix.provider }})
**Risk Level:** ${summary.risk_level}
**Risk Score:** ${summary.risk_score}/100
**Summary:**
- 🔴 Critical: ${summary.critical_findings}
- 📊 Total Findings: ${summary.total_findings}
- 📋 Compliance: ${summary.compliance_status}
**Top Services at Risk:**
${summary.top_services_at_risk.slice(0, 3).map(s =>
`- ${s.service}: ${s.critical_findings} critical findings`
).join('\n')}
${summary.risk_level === 'CRITICAL' ? '⚠️ **Critical security issues found! Please review and remediate.**' : '✅ No critical security issues found.'}
[View detailed report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
consolidate-results:
needs: scoutsuite-scan
runs-on: ubuntu-latest
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v3
- name: Consolidate multi-cloud results
run: |
mkdir -p consolidated_results
# Combine results from all providers
python << 'EOF'
import json
import glob
import os
consolidated_summary = {
"scan_timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"providers": {},
"overall_risk_score": 0,
"total_critical_findings": 0,
"total_findings": 0
}
providers = ["aws", "azure", "gcp"]
total_risk_score = 0
provider_count = 0
for provider in providers:
analysis_pattern = f"scoutsuite-results-{provider}/scoutsuite_analysis_*.json"
analysis_files = glob.glob(analysis_pattern)
if analysis_files:
with open(analysis_files[0], 'r') as f:
data = json.load(f)
summary = data['executive_summary']
consolidated_summary["providers"][provider] = summary
consolidated_summary["total_critical_findings"] += summary['critical_findings']
consolidated_summary["total_findings"] += summary['total_findings']
total_risk_score += summary['risk_score']
provider_count += 1
if provider_count > 0:
consolidated_summary["overall_risk_score"] = round(total_risk_score / provider_count, 1)
# Save consolidated results
with open('consolidated_results/multi_cloud_security_summary.json', 'w') as f:
json.dump(consolidated_summary, f, indent=2)
print(f"Multi-cloud security summary generated")
print(f"Overall risk score: {consolidated_summary['overall_risk_score']}")
print(f"Total critical findings: {consolidated_summary['total_critical_findings']}")
EOF
- name: Upload consolidated results
uses: actions/upload-artifact@v3
with:
name: scoutsuite-consolidated-results
path: consolidated_results/
Optimisation des performances et dépannage
Optimisation des performances
#!/bin/bash
# ScoutSuite performance optimization
optimize_scoutsuite_performance() {
echo "Optimizing ScoutSuite performance..."
# 1. Create performance configuration
cat > scoutsuite_performance_config.json << 'EOF'
{
"performance": {
"max_workers": 10,
"timeout": 300,
"retry_attempts": 3,
"retry_delay": 5,
"rate_limiting": {
"enabled": true,
"requests_per_second": 10
}
},
"scanning": {
"skip_empty_regions": true,
"parallel_service_scanning": true,
"cache_results": true,
"cache_duration": 3600
},
"output": {
"compress_reports": true,
"minimal_output": false,
"include_raw_data": false
}
}
EOF
# 2. Create optimized scanning script
cat > optimized_scoutsuite_scan.sh << 'EOF'
#!/bin/bash
# Optimized ScoutSuite scanning script
# Performance environment variables
export PYTHONUNBUFFERED=1
export PYTHONDONTWRITEBYTECODE=1
# Function to run optimized scan
run_optimized_scan() {
local provider="$1"
local regions="$2"
local services="$3"
local output_dir="$4"
echo "Running optimized scan for $provider..."
case "$provider" in
aws)
# Use timeout to prevent hanging
timeout 3600 scout aws \
--regions "$regions" \
--services "$services" \
--report-dir "$output_dir" \
--report-name "optimized_${provider}_scan" \
--no-browser \
--max-workers 8 \
--quiet
;;
azure)
timeout 3600 scout azure \
--services "$services" \
--report-dir "$output_dir" \
--report-name "optimized_${provider}_scan" \
--no-browser \
--max-workers 8 \
--quiet
;;
gcp)
timeout 3600 scout gcp \
--services "$services" \
--report-dir "$output_dir" \
--report-name "optimized_${provider}_scan" \
--no-browser \
--max-workers 8 \
--quiet
;;
esac
local exit_code=$?
if [ $exit_code -eq 124 ]; then
echo "Warning: Scan for $provider timed out"
elif [ $exit_code -ne 0 ]; then
echo "Error: Scan for $provider failed with exit code $exit_code"
else
echo "Completed scan for $provider"
fi
return $exit_code
}
# Main optimization function
main() {
local timestamp=$(date +%Y%m%d_%H%M%S)
local output_dir="optimized_scan_$timestamp"
mkdir -p "$output_dir"
# Essential services for quick scan
local aws_services="iam,s3,ec2,vpc"
local azure_services="keyvault,storage,network"
local gcp_services="iam,storage,compute"
# Essential regions
local aws_regions="us-east-1,us-west-2,eu-west-1"
echo "Starting optimized ScoutSuite scan..."
# Run scans in parallel
run_optimized_scan "aws" "$aws_regions" "$aws_services" "$output_dir" &
AWS_PID=$!
run_optimized_scan "azure" "" "$azure_services" "$output_dir" &
AZURE_PID=$!
run_optimized_scan "gcp" "" "$gcp_services" "$output_dir" &
GCP_PID=$!
# Wait for all scans to complete
wait $AWS_PID
wait $AZURE_PID
wait $GCP_PID
echo "Optimized scan completed. Results in: $output_dir"
}
# Run optimization
main "$@"
EOF
chmod +x optimized_scoutsuite_scan.sh
echo "Performance optimization setup complete"
}
# Memory optimization
optimize_memory_usage() {
echo "Optimizing ScoutSuite memory usage..."
# Create memory monitoring script
cat > monitor_scoutsuite_memory.sh << 'EOF'
#!/bin/bash
# Monitor ScoutSuite memory usage
SCOUTSUITE_PID=""
MEMORY_LOG="scoutsuite_memory.log"
# Function to monitor resources
monitor_resources() {
echo "Timestamp,Memory_MB,CPU_Percent" > "$MEMORY_LOG"
while true; do
if [ -n "$SCOUTSUITE_PID" ] && kill -0 "$SCOUTSUITE_PID" 2>/dev/null; then
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Memory usage in MB
memory_kb=$(ps -p "$SCOUTSUITE_PID" -o rss --no-headers 2>/dev/null)
if [ -n "$memory_kb" ]; then
memory_mb=$((memory_kb / 1024))
# CPU usage
cpu_percent=$(ps -p "$SCOUTSUITE_PID" -o %cpu --no-headers 2>/dev/null)
echo "$timestamp,$memory_mb,$cpu_percent" >> "$MEMORY_LOG"
fi
else
break
fi
sleep 10
done
}
# Start monitoring in background
monitor_resources &
MONITOR_PID=$!
# Run ScoutSuite with memory optimization
export PYTHONUNBUFFERED=1
export PYTHONDONTWRITEBYTECODE=1
# Start ScoutSuite and capture PID
scout aws --regions us-east-1 --services iam --no-browser &
SCOUTSUITE_PID=$!
# Wait for ScoutSuite to complete
wait $SCOUTSUITE_PID
# Stop monitoring
kill $MONITOR_PID 2>/dev/null
# Analyze memory usage
python3 << 'PYTHON'
import pandas as pd
import matplotlib.pyplot as plt
try:
# Read memory data
memory_df = pd.read_csv('scoutsuite_memory.log')
memory_df['Timestamp'] = pd.to_datetime(memory_df['Timestamp'])
# Create memory usage chart
plt.figure(figsize=(12, 8))
plt.subplot(2, 1, 1)
plt.plot(memory_df['Timestamp'], memory_df['Memory_MB'])
plt.title('ScoutSuite Memory Usage Over Time')
plt.ylabel('Memory Usage (MB)')
plt.grid(True)
plt.subplot(2, 1, 2)
plt.plot(memory_df['Timestamp'], memory_df['CPU_Percent'])
plt.title('ScoutSuite CPU Usage Over Time')
plt.xlabel('Time')
plt.ylabel('CPU Usage (%)')
plt.grid(True)
plt.tight_layout()
plt.savefig('scoutsuite_resource_usage.png')
# Print statistics
print(f"Average Memory Usage: {memory_df['Memory_MB'].mean():.1f} MB")
print(f"Peak Memory Usage: {memory_df['Memory_MB'].max():.1f} MB")
print(f"Average CPU Usage: {memory_df['CPU_Percent'].mean():.1f}%")
print(f"Peak CPU Usage: {memory_df['CPU_Percent'].max():.1f}%")
except Exception as e:
print(f"Error analyzing resource usage: {e}")
PYTHON
echo "Memory monitoring completed"
EOF
chmod +x monitor_scoutsuite_memory.sh
echo "Memory optimization complete"
}
# Run optimizations
optimize_scoutsuite_performance
optimize_memory_usage
Guide de dépannage
#!/bin/bash
# ScoutSuite troubleshooting guide
troubleshoot_scoutsuite() {
echo "ScoutSuite Troubleshooting Guide"
echo "================================"
# Check Python installation
if ! command -v python3 &> /dev/null; then
echo "❌ Python 3 not found"
echo "Solution: Install Python 3.7 or later"
echo " sudo apt update && sudo apt install python3 python3-pip"
return 1
fi
python_version=$(python3 --version | cut -d' ' -f2)
echo "✅ Python found: $python_version"
# Check ScoutSuite installation
if ! command -v scout &> /dev/null; then
echo "❌ ScoutSuite not found"
echo "Solution: Install ScoutSuite"
echo " pip3 install scoutsuite"
return 1
fi
scout_version=$(scout --version 2>&1 | head -n1)
echo "✅ ScoutSuite found: $scout_version"
# Check cloud CLI tools
echo ""
echo "Checking cloud CLI tools..."
# AWS CLI
if command -v aws &> /dev/null; then
aws_version=$(aws --version 2>&1)
echo "✅ AWS CLI found: $aws_version"
if aws sts get-caller-identity > /dev/null 2>&1; then
account_id=$(aws sts get-caller-identity --query Account --output text)
echo "✅ AWS credentials configured (Account: $account_id)"
else
echo "⚠️ AWS credentials not configured"
fi
else
echo "⚠️ AWS CLI not found"
fi
# Azure CLI
if command -v az &> /dev/null; then
azure_version=$(az --version | head -n1)
echo "✅ Azure CLI found: $azure_version"
if az account show > /dev/null 2>&1; then
subscription_id=$(az account show --query id --output tsv)
echo "✅ Azure credentials configured (Subscription: $subscription_id)"
else
echo "⚠️ Azure credentials not configured"
fi
else
echo "⚠️ Azure CLI not found"
fi
# Google Cloud SDK
if command -v gcloud &> /dev/null; then
gcloud_version=$(gcloud --version | head -n1)
echo "✅ Google Cloud SDK found: $gcloud_version"
if gcloud auth list --filter=status:ACTIVE --format="value(account)" | head -n1 > /dev/null 2>&1; then
project_id=$(gcloud config get-value project 2>/dev/null)
echo "✅ GCP credentials configured (Project: $project_id)"
else
echo "⚠️ GCP credentials not configured"
fi
else
echo "⚠️ Google Cloud SDK not found"
fi
# Test basic functionality
echo ""
echo "Testing basic functionality..."
if scout --help > /dev/null 2>&1; then
echo "✅ ScoutSuite help command works"
else
echo "❌ ScoutSuite help command failed"
echo "Solution: Reinstall ScoutSuite"
echo " pip3 uninstall scoutsuite && pip3 install scoutsuite"
fi
# Check system resources
echo ""
echo "Checking system resources..."
available_memory=$(free -m | awk 'NR==2{printf "%.1f", $7/1024}')
if (( $(echo "$available_memory < 2.0" | bc -l) )); then
echo "⚠️ Low available memory: ${available_memory}GB"
echo "Recommendation: Ensure at least 4GB available memory for large scans"
else
echo "✅ Available memory: ${available_memory}GB"
fi
# Check disk space
disk_usage=$(df . | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$disk_usage" -gt 90 ]; then
echo "⚠️ High disk usage: ${disk_usage}%"
echo "Solution: Free up disk space"
else
echo "✅ Disk usage: ${disk_usage}%"
fi
echo ""
echo "Troubleshooting completed"
}
# Common error solutions
fix_common_errors() {
echo "Common ScoutSuite Errors and Solutions"
echo "====================================="
cat << 'EOF'
1. "ModuleNotFoundError: No module named 'ScoutSuite'"
Solution:
- Install ScoutSuite: pip3 install scoutsuite
- Check Python path: python3 -c "import sys; print(sys.path)"
2. "AWS credentials not configured"
Solution:
- Run: aws configure
- Or set environment variables:
export AWS_ACCESS_KEY_ID=your-key
export AWS_SECRET_ACCESS_KEY=your-secret
3. "Azure credentials not configured"
Solution:
- Run: az login
- Or use service principal:
export AZURE_CLIENT_ID=your-client-id
export AZURE_CLIENT_SECRET=your-client-secret
export AZURE_TENANT_ID=your-tenant-id
4. "GCP credentials not configured"
Solution:
- Run: gcloud auth login
- Or use service account:
export GOOGLE_APPLICATION_CREDENTIALS=path/to/key.json
5. "AccessDenied" or "Forbidden" errors
Solution:
- Check IAM permissions
- Ensure user/role has required policies attached
- Use ScoutSuite IAM policies from documentation
6. "Timeout" or "Connection timeout"
Solution:
- Increase timeout: --timeout 3600
- Check internet connectivity
- Reduce parallel requests: --max-workers 5
7. "Memory allocation failed" or "Out of memory"
Solution:
- Scan fewer regions: --regions us-east-1
- Scan specific services: --services s3,iam
- Increase system memory
8. "Report generation failed"
Solution:
- Check disk space
- Ensure write permissions in output directory
- Use different output directory: --report-dir /tmp/scoutsuite
9. "SSL/TLS certificate errors"
Solution:
- Update certificates: sudo apt update && sudo apt install ca-certificates
- Check system time: timedatectl status
- Update Python requests: pip3 install --upgrade requests
10. "Scan takes too long" or "Hangs"
Solution:
- Use region filtering: --regions us-east-1
- Scan specific services: --services iam,s3
- Monitor with timeout: timeout 3600 scout aws
- Use fewer workers: --max-workers 3
EOF
}
# Performance diagnostics
diagnose_performance() {
echo "Diagnosing ScoutSuite Performance"
echo "================================="
# Test scan performance
echo "Running performance test..."
start_time=$(date +%s.%N)
# Run a simple scan
timeout 300 scout aws --regions us-east-1 --services iam --no-browser > /dev/null 2>&1
exit_code=$?
end_time=$(date +%s.%N)
duration=$(echo "$end_time - $start_time" | bc)
if [ $exit_code -eq 0 ]; then
echo "✅ Performance test completed in ${duration}s"
elif [ $exit_code -eq 124 ]; then
echo "⚠️ Performance test timed out (>300s)"
echo "Recommendation: Check network connectivity and cloud API performance"
else
echo "❌ Performance test failed"
echo "Recommendation: Check configuration and credentials"
fi
# Check Python performance
python_startup_time=$(python3 -c "import time; start=time.time(); import ScoutSuite; print(f'{time.time()-start:.2f}')" 2>/dev/null || echo "N/A")
echo "Python import time: ${python_startup_time}s"
# System load
load_avg=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
echo "System load average: $load_avg"
# Network connectivity test
echo "Testing cloud API connectivity..."
# AWS API test
if command -v aws &> /dev/null; then
aws_api_time=$(time (aws sts get-caller-identity > /dev/null 2>&1) 2>&1 | grep real | awk '{print $2}')
echo "AWS API response time: $aws_api_time"
fi
# Azure API test
if command -v az &> /dev/null; then
azure_api_time=$(time (az account show > /dev/null 2>&1) 2>&1 | grep real | awk '{print $2}')
echo "Azure API response time: $azure_api_time"
fi
# GCP API test
if command -v gcloud &> /dev/null; then
gcp_api_time=$(time (gcloud auth list > /dev/null 2>&1) 2>&1 | grep real | awk '{print $2}')
echo "GCP API response time: $gcp_api_time"
fi
# Recommendations
echo ""
echo "Performance Recommendations:"
echo "- Use region filtering for faster scans"
echo "- Scan specific services instead of all services"
echo "- Use --max-workers to control parallelism"
echo "- Increase system memory for large environments"
echo "- Use SSD storage for better I/O performance"
echo "- Monitor cloud API rate limits"
echo "- Use --no-browser for headless environments"
}
# Main troubleshooting function
main() {
troubleshoot_scoutsuite
echo ""
fix_common_errors
echo ""
diagnose_performance
}
# Run troubleshooting
main
Ressources et documentation
Ressources officielles
- [ScoutSuite GitHub Repository] (LINK_12) - Code source et documentation
- [ScoutSuite Wiki] (LINK_12) - Documentation et guides complets
- Blogue du groupe CNC - Recherche sur la sécurité et mises à jour ScoutSuite
- [ScoutSuite Rules Database] (LINK_12) - Règles et contrôles de sécurité disponibles
Ressources du fournisseur de cloud
- [Meilleures pratiques en matière de sécurité AWS] (LINK_12) - Lignes directrices en matière de sécurité AWS
- Documentation de sécurité de l'Azure - Pratiques exemplaires en matière de sécurité de l'Azure
- [Google Cloud Security] (LINK_12) - Documentation de sécurité GCP
- Cadre de sécurité multi-clouds - Cadre de cybersécurité NIST
Exemples d'intégration
- ScoutSuite IC/CD Examples - Exemples officiels d'intégration
- [Module Terraform ScoutSuite] (LINK_12) - Intégration Terraform
- Modèles CloudFormation - Modèles de déploiement CloudFormation
- [Déploiement Kubernetes] (LINK_12) - Exemples de déploiement Kubernetes