Files

163 lines
5.5 KiB
Python

#!/usr/bin/env python3
"""
AWS Macie Data Classification Management Script
Automates Macie configuration, job creation, and findings analysis.
"""
import boto3
import json
import sys
from datetime import datetime
def enable_macie(session):
"""Enable Macie in the current account."""
client = session.client('macie2')
try:
client.enable_macie(status='ENABLED')
print("[+] Macie enabled successfully")
except client.exceptions.ConflictException:
print("[*] Macie is already enabled")
# Enable automated discovery
try:
client.update_automated_discovery_configuration(status='ENABLED')
print("[+] Automated discovery enabled")
except Exception as e:
print(f"[!] Could not enable automated discovery: {e}")
def create_classification_job(session, bucket_names, account_id, job_name=None):
"""Create a one-time classification job for specified buckets."""
client = session.client('macie2')
if not job_name:
job_name = f"scan-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
response = client.create_classification_job(
jobType='ONE_TIME',
name=job_name,
s3JobDefinition={
'bucketDefinitions': [{
'accountId': account_id,
'buckets': bucket_names
}]
},
managedDataIdentifierSelector='ALL'
)
job_id = response['jobId']
print(f"[+] Classification job created: {job_id}")
return job_id
def list_findings(session, severity=None, max_results=25):
"""List Macie findings with optional severity filter."""
client = session.client('macie2')
criteria = {}
if severity:
criteria['severity.description'] = {'eq': [severity]}
response = client.list_findings(
findingCriteria={'criterion': criteria} if criteria else {},
sortCriteria={'attributeName': 'updatedAt', 'orderBy': 'DESC'},
maxResults=max_results
)
finding_ids = response.get('findingIds', [])
print(f"[+] Found {len(finding_ids)} findings")
if finding_ids:
details = client.get_findings(findingIds=finding_ids[:20])
for finding in details.get('findings', []):
severity_desc = finding['severity']['description']
category = finding.get('category', 'N/A')
title = finding.get('title', 'N/A')
bucket = finding.get('resourcesAffected', {}).get('s3Bucket', {}).get('name', 'N/A')
print(f" [{severity_desc}] {title}")
print(f" Bucket: {bucket} | Category: {category}")
return finding_ids
def get_bucket_statistics(session):
"""Get Macie statistics for all monitored S3 buckets."""
client = session.client('macie2')
response = client.describe_buckets(
criteria={},
maxResults=50
)
buckets = response.get('buckets', [])
print(f"\n[+] Monitoring {len(buckets)} S3 buckets:")
print(f"{'Bucket':<40} {'Encryption':<15} {'Public':<10} {'Shared':<10} {'Objects':<10}")
print("-" * 85)
for bucket in buckets:
name = bucket.get('bucketName', 'N/A')
encryption = bucket.get('serverSideEncryption', {}).get('type', 'NONE')
public_access = bucket.get('publicAccess', {}).get('effectivePermission', 'NOT_PUBLIC')
shared = bucket.get('sharedAccess', 'NOT_SHARED')
obj_count = bucket.get('objectCount', 0)
public_flag = "YES" if public_access == "PUBLIC" else "NO"
shared_flag = "YES" if shared != "NOT_SHARED" else "NO"
print(f"{name:<40} {encryption:<15} {public_flag:<10} {shared_flag:<10} {obj_count:<10}")
return buckets
def get_usage_stats(session):
"""Get Macie usage statistics."""
client = session.client('macie2')
response = client.get_usage_totals()
usage = response.get('usageTotals', [])
print("\n[+] Macie Usage Statistics:")
for item in usage:
usage_type = item.get('type', 'N/A')
amount = item.get('estimatedCost', 0)
currency = item.get('currency', 'USD')
print(f" {usage_type}: ${amount:.2f} {currency}")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="AWS Macie Management")
parser.add_argument("--enable", action="store_true", help="Enable Macie")
parser.add_argument("--scan", nargs="+", help="Create scan job for buckets")
parser.add_argument("--account-id", type=str, help="AWS account ID for scan")
parser.add_argument("--findings", action="store_true", help="List findings")
parser.add_argument("--severity", type=str, choices=["Low", "Medium", "High"], help="Filter by severity")
parser.add_argument("--buckets", action="store_true", help="Show bucket statistics")
parser.add_argument("--usage", action="store_true", help="Show usage statistics")
parser.add_argument("--region", type=str, default="us-east-1", help="AWS region")
parser.add_argument("--profile", type=str, help="AWS profile name")
args = parser.parse_args()
session_kwargs = {"region_name": args.region}
if args.profile:
session_kwargs["profile_name"] = args.profile
session = boto3.Session(**session_kwargs)
if args.enable:
enable_macie(session)
if args.scan:
if not args.account_id:
sts = session.client('sts')
args.account_id = sts.get_caller_identity()['Account']
create_classification_job(session, args.scan, args.account_id)
if args.findings:
list_findings(session, severity=args.severity)
if args.buckets:
get_bucket_statistics(session)
if args.usage:
get_usage_stats(session)