Skip to content

Instantly share code, notes, and snippets.

@dileeph
Created March 14, 2025 18:53
Show Gist options
  • Save dileeph/ec828174d3e1032451c6b53fc06220a0 to your computer and use it in GitHub Desktop.
Save dileeph/ec828174d3e1032451c6b53fc06220a0 to your computer and use it in GitHub Desktop.
aws resources scanner. takes credentials from aws config
#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Create output directory with timestamp
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="aws_resource_scan_${TIMESTAMP}"
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}/global"
mkdir -p "${OUTPUT_DIR}/regions"
# Log file
LOG_FILE="${OUTPUT_DIR}/scan.log"
# Arrays to track scanned and skipped regions
declare -a scanned_regions
declare -a skipped_regions
# Add usage function
usage() {
echo "Usage: $0 [region_starts_with...]"
echo "Examples:"
echo " $0 # Scan all regions"
echo " $0 us eu # Scan regions starting with 'us' or 'eu'"
echo " $0 ap-south # Scan regions starting with 'ap-south'"
}
# Function to log messages
log() {
echo -e "${2:-$GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$LOG_FILE"
}
# Get default region
get_default_region() {
DEFAULT_REGION=${AWS_DEFAULT_REGION:-${AWS_REGION}}
if [ -z "$DEFAULT_REGION" ]; then
DEFAULT_REGION=$(aws configure get region)
fi
echo ${DEFAULT_REGION:-us-east-1}
}
# Get all AWS regions
get_all_regions() {
local region_filters=("$@")
local all_regions=$(aws ec2 describe-regions \
--all-regions \
--query 'Regions[].RegionName' \
--output text)
# If no filters provided, return all regions
if [ ${#region_filters[@]} -eq 0 ]; then
echo "$all_regions"
return
fi
# Filter regions based on provided prefixes
local filtered_regions=""
for region in $all_regions; do
for filter in "${region_filters[@]}"; do
if [[ $region == ${filter}* ]]; then
filtered_regions+="$region "
break
fi
done
done
echo "$filtered_regions"
}
# Function to display selected regions
display_selected_regions() {
local regions=($1)
local total=${#regions[@]}
log "Selected Regions for Scanning:" "$BLUE"
for region in "${regions[@]}"; do
log " - $region" "$YELLOW"
done
log "Total regions to scan: $total" "$BLUE"
# Ask for confirmation
read -p "Do you want to continue with these regions? (y/n): " confirm
if [[ $confirm != [yY] ]]; then
log "Scan cancelled by user" "$RED"
exit 1
fi
}
# Function to prompt for region confirmation
confirm_region_scan() {
local region=$1
while true; do
read -p "Do you want to scan region ${region}? (y/n/q - y:scan, n:skip, q:quit): " choice
case "$choice" in
[Yy]) return 0 ;; # Proceed with scan
[Nn]) return 1 ;; # Skip this region
[Qq]) log "Scan cancelled by user" "$RED"; exit 0 ;;
*) echo "Please answer y(es), n(o), or q(uit)" ;;
esac
done
}
# Check prerequisites
check_prerequisites() {
log "Checking prerequisites..." "$BLUE"
if ! command -v aws &> /dev/null; then
log "AWS CLI is not installed. Please install it first." "$RED"
exit 1
fi
if ! command -v jq &> /dev/null; then
log "jq is not installed. Please install it first." "$RED"
exit 1
fi
if ! aws sts get-caller-identity &> /dev/null; then
log "AWS credentials not configured. Please run 'aws configure'" "$RED"
exit 1
fi
}
# Scan Global Services
scan_global_services() {
log "Scanning Global Services..." "$BLUE"
# IAM Resources
log "Scanning IAM Resources..." "$YELLOW"
aws iam list-users --output json > "${OUTPUT_DIR}/global/iam_users.json"
aws iam list-roles --output json > "${OUTPUT_DIR}/global/iam_roles.json"
aws iam list-policies --scope Local --output json > "${OUTPUT_DIR}/global/iam_policies.json"
aws iam list-groups --output json > "${OUTPUT_DIR}/global/iam_groups.json"
# Route 53
log "Scanning Route 53 Resources..." "$YELLOW"
aws route53 list-hosted-zones --output json > "${OUTPUT_DIR}/global/route53_zones.json"
aws route53 list-health-checks --output json > "${OUTPUT_DIR}/global/route53_health_checks.json"
# WAF & Shield
log "Scanning WAF Resources..." "$YELLOW"
aws waf list-web-acls --output json > "${OUTPUT_DIR}/global/waf_acls.json" 2>/dev/null
aws wafv2 list-web-acls --scope REGIONAL --output json > "${OUTPUT_DIR}/global/wafv2_regional_acls.json" 2>/dev/null
aws wafv2 list-web-acls --scope CLOUDFRONT --output json > "${OUTPUT_DIR}/global/wafv2_cloudfront_acls.json" 2>/dev/null
aws shield get-subscription-state --output json > "${OUTPUT_DIR}/global/shield_subscription.json" 2>/dev/null
# CloudFront
log "Scanning CloudFront Resources..." "$YELLOW"
aws cloudfront list-distributions --output json > "${OUTPUT_DIR}/global/cloudfront_distributions.json"
# S3
log "Scanning S3 Resources..." "$YELLOW"
aws s3api list-buckets --output json > "${OUTPUT_DIR}/global/s3_buckets.json"
# Organizations
log "Scanning Organizations..." "$YELLOW"
aws organizations list-accounts --output json > "${OUTPUT_DIR}/global/org_accounts.json" 2>/dev/null
aws organizations list-organizational-units-for-parent --parent-id root --output json > "${OUTPUT_DIR}/global/org_units.json" 2>/dev/null
}
# Scan Regional Services
scan_regional_services() {
local region=$1
local current_index=$2
local total_regions=$3
log "Scanning region: ${region} (${current_index}/${total_regions})" "$BLUE"
mkdir -p "${OUTPUT_DIR}/regions/${region}"
local REGION_DIR="${OUTPUT_DIR}/regions/${region}"
# EC2 Resources
log "Scanning EC2 Resources in ${region}..." "$YELLOW"
aws ec2 describe-instances --region "$region" --output json > "${REGION_DIR}/ec2_instances.json"
aws ec2 describe-vpcs --region "$region" --output json > "${REGION_DIR}/vpcs.json"
aws ec2 describe-security-groups --region "$region" --output json > "${REGION_DIR}/security_groups.json"
aws ec2 describe-network-acls --region "$region" --output json > "${REGION_DIR}/network_acls.json"
aws ec2 describe-route-tables --region "$region" --output json > "${REGION_DIR}/route_tables.json"
aws ec2 describe-nat-gateways --region "$region" --output json > "${REGION_DIR}/nat_gateways.json"
aws ec2 describe-internet-gateways --region "$region" --output json > "${REGION_DIR}/internet_gateways.json"
aws ec2 describe-volumes --region "$region" --output json > "${REGION_DIR}/ebs_volumes.json"
aws ec2 describe-snapshots --owner-ids self --region "$region" --output json > "${REGION_DIR}/ebs_snapshots.json"
# Load Balancers
log "Scanning Load Balancers in ${region}..." "$YELLOW"
aws elbv2 describe-load-balancers --region "$region" --output json > "${REGION_DIR}/load_balancers.json"
aws elbv2 describe-target-groups --region "$region" --output json > "${REGION_DIR}/target_groups.json"
# Auto Scaling
log "Scanning Auto Scaling in ${region}..." "$YELLOW"
aws autoscaling describe-auto-scaling-groups --region "$region" --output json > "${REGION_DIR}/auto_scaling_groups.json"
aws autoscaling describe-launch-configurations --region "$region" --output json > "${REGION_DIR}/launch_configurations.json"
# Lambda
log "Scanning Lambda in ${region}..." "$YELLOW"
aws lambda list-functions --region "$region" --output json > "${REGION_DIR}/lambda_functions.json"
aws lambda list-layers --region "$region" --output json > "${REGION_DIR}/lambda_layers.json"
# API Gateway
log "Scanning API Gateway in ${region}..." "$YELLOW"
aws apigateway get-rest-apis --region "$region" --output json > "${REGION_DIR}/api_gateway_apis.json"
aws apigatewayv2 get-apis --region "$region" --output json > "${REGION_DIR}/api_gateway_v2_apis.json"
# Container Services
log "Scanning Container Services in ${region}..." "$YELLOW"
aws ecr describe-repositories --region "$region" --output json > "${REGION_DIR}/ecr_repositories.json"
aws ecs list-clusters --region "$region" --output json > "${REGION_DIR}/ecs_clusters.json"
aws eks list-clusters --region "$region" --output json > "${REGION_DIR}/eks_clusters.json"
# Database Services
log "Scanning Database Services in ${region}..." "$YELLOW"
aws rds describe-db-instances --region "$region" --output json > "${REGION_DIR}/rds_instances.json"
aws dynamodb list-tables --region "$region" --output json > "${REGION_DIR}/dynamodb_tables.json"
aws elasticache describe-cache-clusters --region "$region" --output json > "${REGION_DIR}/elasticache_clusters.json"
aws redshift describe-clusters --region "$region" --output json > "${REGION_DIR}/redshift_clusters.json"
# SNS & SQS
log "Scanning Messaging Services in ${region}..." "$YELLOW"
aws sns list-topics --region "$region" --output json > "${REGION_DIR}/sns_topics.json"
aws sqs list-queues --region "$region" --output json > "${REGION_DIR}/sqs_queues.json"
# CloudWatch
log "Scanning CloudWatch in ${region}..." "$YELLOW"
aws cloudwatch describe-alarms --region "$region" --output json > "${REGION_DIR}/cloudwatch_alarms.json"
aws logs describe-log-groups --region "$region" --output json > "${REGION_DIR}/cloudwatch_log_groups.json"
# Additional Services
log "Scanning Additional Services in ${region}..." "$YELLOW"
aws kms list-keys --region "$region" --output json > "${REGION_DIR}/kms_keys.json"
aws secretsmanager list-secrets --region "$region" --output json > "${REGION_DIR}/secrets.json"
aws stepfunctions list-state-machines --region "$region" --output json > "${REGION_DIR}/step_functions.json"
aws events list-rules --region "$region" --output json > "${REGION_DIR}/eventbridge_rules.json"
# Modify the "Additional Services" section in scan_regional_services() to include more services:
# Security Services
log "Scanning Security Services in ${region}..." "$YELLOW"
aws kms list-keys --region "$region" --output json > "${REGION_DIR}/kms_keys.json"
aws kms list-aliases --region "$region" --output json > "${REGION_DIR}/kms_aliases.json"
aws secretsmanager list-secrets --region "$region" --output json > "${REGION_DIR}/secrets.json"
aws acm list-certificates --region "$region" --output json > "${REGION_DIR}/acm_certificates.json"
aws guardduty list-detectors --region "$region" --output json > "${REGION_DIR}/guardduty_detectors.json"
aws securityhub list-enabled-products-for-import --region "$region" --output json > "${REGION_DIR}/securityhub_products.json" 2>/dev/null
# Storage Services
log "Scanning Storage Services in ${region}..." "$YELLOW"
aws efs describe-file-systems --region "$region" --output json > "${REGION_DIR}/efs_filesystems.json"
aws fsx describe-file-systems --region "$region" --output json > "${REGION_DIR}/fsx_filesystems.json"
aws backup list-backup-vaults --region "$region" --output json > "${REGION_DIR}/backup_vaults.json"
# Analytics Services
log "Scanning Analytics Services in ${region}..." "$YELLOW"
aws opensearch list-domain-names --region "$region" --output json > "${REGION_DIR}/opensearch_domains.json"
aws kinesis list-streams --region "$region" --output json > "${REGION_DIR}/kinesis_streams.json"
aws firehose list-delivery-streams --region "$region" --output json > "${REGION_DIR}/firehose_streams.json"
aws athena list-work-groups --region "$region" --output json > "${REGION_DIR}/athena_workgroups.json"
aws emr list-clusters --region "$region" --output json > "${REGION_DIR}/emr_clusters.json"
# Integration Services
log "Scanning Integration Services in ${region}..." "$YELLOW"
aws mq list-brokers --region "$region" --output json > "${REGION_DIR}/mq_brokers.json"
aws kafka list-clusters --region "$region" --output json > "${REGION_DIR}/msk_clusters.json"
aws events list-event-buses --region "$region" --output json > "${REGION_DIR}/eventbridge_buses.json"
# Developer Tools
log "Scanning Developer Tools in ${region}..." "$YELLOW"
aws codecommit list-repositories --region "$region" --output json > "${REGION_DIR}/codecommit_repos.json"
aws codebuild list-projects --region "$region" --output json > "${REGION_DIR}/codebuild_projects.json"
aws codepipeline list-pipelines --region "$region" --output json > "${REGION_DIR}/codepipeline_pipelines.json"
# Machine Learning
log "Scanning Machine Learning Services in ${region}..." "$YELLOW"
aws sagemaker list-notebook-instances --region "$region" --output json > "${REGION_DIR}/sagemaker_notebooks.json"
aws sagemaker list-endpoints --region "$region" --output json > "${REGION_DIR}/sagemaker_endpoints.json"
aws sagemaker list-training-jobs --region "$region" --output json > "${REGION_DIR}/sagemaker_training.json"
# Application Integration
log "Scanning Application Integration in ${region}..." "$YELLOW"
aws sfn list-state-machines --region "$region" --output json > "${REGION_DIR}/step_functions.json"
aws appflow list-flows --region "$region" --output json > "${REGION_DIR}/appflow_flows.json"
aws servicecatalog search-products --region "$region" --output json > "${REGION_DIR}/servicecatalog_products.json"
}
# Generate summary
generate_summary() {
log "Generating Summary Report..." "$BLUE"
SUMMARY_FILE="${OUTPUT_DIR}/summary_report.txt"
echo "AWS Resource Usage Summary" > "$SUMMARY_FILE"
echo "Generated on: $(date)" >> "$SUMMARY_FILE"
echo "Default Region: $(get_default_region)" >> "$SUMMARY_FILE"
echo "----------------------------------------" >> "$SUMMARY_FILE"
# Add scan coverage information
echo -e "\nScan Coverage:" >> "$SUMMARY_FILE"
echo "----------------------------------------" >> "$SUMMARY_FILE"
echo "Total Regions Available: ${#REGIONS[@]}" >> "$SUMMARY_FILE"
echo "Regions Scanned: ${#scanned_regions[@]}" >> "$SUMMARY_FILE"
echo "Regions Skipped: ${#skipped_regions[@]}" >> "$SUMMARY_FILE"
echo -e "\nScanned Regions: ${scanned_regions[*]}" >> "$SUMMARY_FILE"
echo -e "Skipped Regions: ${skipped_regions[*]}" >> "$SUMMARY_FILE"
echo "----------------------------------------" >> "$SUMMARY_FILE"
# Global Resources Summary
echo -e "\nGlobal Resources:" >> "$SUMMARY_FILE"
echo "----------------------------------------" >> "$SUMMARY_FILE"
# Summarize IAM
local user_count=$(jq '.Users | length' "${OUTPUT_DIR}/global/iam_users.json" 2>/dev/null || echo "0")
local role_count=$(jq '.Roles | length' "${OUTPUT_DIR}/global/iam_roles.json" 2>/dev/null || echo "0")
local policy_count=$(jq '.Policies | length' "${OUTPUT_DIR}/global/iam_policies.json" 2>/dev/null || echo "0")
echo "IAM Users: $user_count" >> "$SUMMARY_FILE"
echo "IAM Roles: $role_count" >> "$SUMMARY_FILE"
echo "IAM Custom Policies: $policy_count" >> "$SUMMARY_FILE"
# Summarize S3
local bucket_count=$(jq '.Buckets | length' "${OUTPUT_DIR}/global/s3_buckets.json" 2>/dev/null || echo "0")
echo "S3 Buckets: $bucket_count" >> "$SUMMARY_FILE"
# Regional Resources Summary
echo -e "\nRegional Resources:" >> "$SUMMARY_FILE"
for region in "${scanned_regions[@]}"; do
echo -e "\nRegion: ${region}" >> "$SUMMARY_FILE"
echo "----------------------------------------" >> "$SUMMARY_FILE"
local REGION_DIR="${OUTPUT_DIR}/regions/${region}"
# EC2 Resources
local instance_count=$(jq '.Reservations[].Instances | length' "${REGION_DIR}/ec2_instances.json" 2>/dev/null | awk '{sum += $1} END {print sum}' || echo "0")
local vpc_count=$(jq '.Vpcs | length' "${REGION_DIR}/vpcs.json" 2>/dev/null || echo "0")
local sg_count=$(jq '.SecurityGroups | length' "${REGION_DIR}/security_groups.json" 2>/dev/null || echo "0")
echo "EC2 Instances: $instance_count" >> "$SUMMARY_FILE"
echo "VPCs: $vpc_count" >> "$SUMMARY_FILE"
echo "Security Groups: $sg_count" >> "$SUMMARY_FILE"
# Database Resources
local rds_count=$(jq '.DBInstances | length' "${REGION_DIR}/rds_instances.json" 2>/dev/null || echo "0")
local dynamodb_count=$(jq '.TableNames | length' "${REGION_DIR}/dynamodb_tables.json" 2>/dev/null || echo "0")
echo "RDS Instances: $rds_count" >> "$SUMMARY_FILE"
echo "DynamoDB Tables: $dynamodb_count" >> "$SUMMARY_FILE"
done
}
# Analyze scan results
analyze_scan_results() {
log "Analyzing scan results..." "$BLUE"
ANALYSIS_FILE="${OUTPUT_DIR}/file_analysis.txt"
echo "AWS Resource Scan File Analysis" > "$ANALYSIS_FILE"
echo "Generated on: $(date)" >> "$ANALYSIS_FILE"
echo "----------------------------------------" >> "$ANALYSIS_FILE"
# Function to check if JSON file has content
check_json_content() {
local file=$1
local description=$2
if [ -f "$file" ]; then
local content=$(jq -r 'tostring' "$file" 2>/dev/null)
local size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [ "$size" -eq 0 ]; then
echo -e "${RED}Empty File${NC}: $description ($file)" | tee -a "$ANALYSIS_FILE"
elif [ "$content" == "null" ] || [ "$content" == "{}" ] || [ "$content" == "[]" ]; then
echo -e "${YELLOW}No Resources${NC}: $description ($file)" | tee -a "$ANALYSIS_FILE"
else
echo -e "${GREEN}Has Content${NC}: $description ($file)" | tee -a "$ANALYSIS_FILE"
fi
fi
}
# Check global resource files
echo -e "\nGlobal Resources:" >> "$ANALYSIS_FILE"
echo "----------------------------------------" >> "$ANALYSIS_FILE"
check_json_content "${OUTPUT_DIR}/global/iam_users.json" "IAM Users"
check_json_content "${OUTPUT_DIR}/global/iam_roles.json" "IAM Roles"
check_json_content "${OUTPUT_DIR}/global/iam_policies.json" "IAM Policies"
check_json_content "${OUTPUT_DIR}/global/s3_buckets.json" "S3 Buckets"
# Check regional resource files for scanned regions only
for region in "${scanned_regions[@]}"; do
echo -e "\nRegion: ${region}" >> "$ANALYSIS_FILE"
echo "----------------------------------------" >> "$ANALYSIS_FILE"
local REGION_DIR="${OUTPUT_DIR}/regions/${region}"
check_json_content "${REGION_DIR}/ec2_instances.json" "EC2 Instances"
check_json_content "${REGION_DIR}/vpcs.json" "VPCs"
check_json_content "${REGION_DIR}/security_groups.json" "Security Groups"
check_json_content "${REGION_DIR}/rds_instances.json" "RDS Instances"
check_json_content "${REGION_DIR}/lambda_functions.json" "Lambda Functions"
# Add more resource checks as needed
# Add these checks inside the regional loop in analyze_scan_results()
check_json_content "${REGION_DIR}/kms_aliases.json" "KMS Aliases"
check_json_content "${REGION_DIR}/acm_certificates.json" "ACM Certificates"
check_json_content "${REGION_DIR}/guardduty_detectors.json" "GuardDuty Detectors"
check_json_content "${REGION_DIR}/securityhub_products.json" "SecurityHub Products"
check_json_content "${REGION_DIR}/efs_filesystems.json" "EFS File Systems"
check_json_content "${REGION_DIR}/fsx_filesystems.json" "FSx File Systems"
check_json_content "${REGION_DIR}/backup_vaults.json" "Backup Vaults"
check_json_content "${REGION_DIR}/opensearch_domains.json" "OpenSearch Domains"
check_json_content "${REGION_DIR}/kinesis_streams.json" "Kinesis Streams"
check_json_content "${REGION_DIR}/firehose_streams.json" "Kinesis Firehose"
check_json_content "${REGION_DIR}/athena_workgroups.json" "Athena Workgroups"
check_json_content "${REGION_DIR}/emr_clusters.json" "EMR Clusters"
check_json_content "${REGION_DIR}/mq_brokers.json" "MQ Brokers"
check_json_content "${REGION_DIR}/msk_clusters.json" "MSK Clusters"
check_json_content "${REGION_DIR}/codecommit_repos.json" "CodeCommit Repositories"
check_json_content "${REGION_DIR}/codebuild_projects.json" "CodeBuild Projects"
check_json_content "${REGION_DIR}/codepipeline_pipelines.json" "CodePipeline Pipelines"
check_json_content "${REGION_DIR}/sagemaker_notebooks.json" "SageMaker Notebooks"
check_json_content "${REGION_DIR}/sagemaker_endpoints.json" "SageMaker Endpoints"
done
# Add skipped regions information
echo -e "\nSkipped Regions:" >> "$ANALYSIS_FILE"
echo "----------------------------------------" >> "$ANALYSIS_FILE"
for region in "${skipped_regions[@]}"; do
echo " - ${region}" >> "$ANALYSIS_FILE"
done
# Generate statistics
echo -e "\nFile Analysis Statistics:" >> "$ANALYSIS_FILE"
echo "----------------------------------------" >> "$ANALYSIS_FILE"
echo "Total files scanned: $(find "${OUTPUT_DIR}" -type f -name "*.json" | wc -l)" >> "$ANALYSIS_FILE"
echo "Files with content: $(grep -c "Has Content" "$ANALYSIS_FILE")" >> "$ANALYSIS_FILE"
echo "Files with no resources: $(grep -c "No Resources" "$ANALYSIS_FILE")" >> "$ANALYSIS_FILE"
echo "Empty files: $(grep -c "Empty File" "$ANALYSIS_FILE")" >> "$ANALYSIS_FILE"
}
# Main function
main() {
# Display help if requested
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi
check_prerequisites
# Get filtered regions based on arguments
REGIONS=($(get_all_regions "$@"))
if [ ${#REGIONS[@]} -eq 0 ]; then
log "No matching regions found for the specified filters" "$RED"
usage
exit 1
fi
# Display selected regions and ask for confirmation
display_selected_regions "${REGIONS[*]}"
log "Starting AWS resource scan..." "$BLUE"
# Scan global services
scan_global_services
# Initialize arrays for tracking
declare -a scanned_regions=()
declare -a skipped_regions=()
total_regions=${#REGIONS[@]}
current_index=1
# Scan each region with confirmation
for region in "${REGIONS[@]}"; do
log "Checking region: ${region}" "$BLUE"
if confirm_region_scan "$region"; then
scan_regional_services "$region" "$current_index" "$total_regions"
scanned_regions+=("$region")
else
log "Skipping region: ${region}" "$YELLOW"
skipped_regions+=("$region")
fi
((current_index++))
done
# Generate summary
generate_summary
# Analyze results
analyze_scan_results
log "Scan complete! Results are in: ${OUTPUT_DIR}" "$GREEN"
log "Check ${OUTPUT_DIR}/summary_report.txt for overview" "$GREEN"
log "Check ${OUTPUT_DIR}/file_analysis.txt for file content analysis" "$GREEN"
}
# Execute main function with all arguments
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment