Skip to content

Commit

Permalink
add index, account count
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Jan 2, 2026
1 parent 5847e40 commit 52e0177
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def find_latest_file(pattern):
return max(files, key=os.path.getctime) if files else None

def main():
parser = argparse.ArgumentParser(description="AWS CloudTrail Audit Assessor - ARN Edition")
parser = argparse.ArgumentParser(description="AWS CloudTrail Audit Assessor")
parser.add_argument("--input", help="JSON file (default: latest audit_results.check_cloudtrail.*.json)")
args = parser.parse_args()

Expand All @@ -30,51 +30,45 @@ def main():
print(f"Error: {e}"); sys.exit(1)

org_id = data[0].get("org_id", "Unknown") if data else "Unknown"
account_count = len(data)

# EXPANDED COLUMN WIDTHS
# Account(15) | OU(30) | Global(25) | Active(15) | Resource(100)
report_width = 230
report_width = 240
print("-" * report_width)
print(f"CLOUDTRAIL ARN ASSESSMENT REPORT | Org ID: {org_id} | Input: {os.path.basename(input_file)}")
print("-" * report_width)
print(f"{'Account ID':<15} | {'OU Path':<30} | {'Global Summary':<25} | {'Active/Stopped':<15} | {'Resource (ARN)'}")
# Added Idx Column to Header
print(f"{'Idx':<5} | {'Account ID':<15} | {'OU Path':<35} | {'Global Summary':<25} | {'Active/Stopped':<15} | {'Resource (ARN)'}")
print("-" * report_width)

stats = {
"s3_bytes": 0, "s3_objects": 0, "s3_buckets": set(),
"cw_bytes": 0, "cw_group_arns": set(),
"sns_topics": set(), "kms_cmk_count": 0, "sse_s3_count": 0,
"logging_active": 0, "logging_stopped": 0,
"total_shadow_regions": 0,
"total_home_regions": 0
"total_shadow_regions": 0, "total_home_regions": 0
}

retention_distribution = Counter()

for account in data:
# Added enumerate to track Index
for idx, account in enumerate(data, 1):
acc_id = account.get("account_id")
ou_path = account.get("ou_path", "Root")
checks = account.get("data", {})
summary = checks.get("account_summary", {}).get("_summary", "UNKNOWN")

acc_active, acc_stopped = 0, 0

# Since one account can have multiple trails, we iterate them
for key, val in checks.items():
if key == "account_summary": continue
if ":" not in key: continue


trail_arn = val.get("resource")
stats["total_home_regions"] += 1
stats["total_shadow_regions"] += int(val.get("shadow_region_count", 0))

trail_arn = val.get("resource") # Now contains the full ARN

if val.get("is_logging") == "True":
acc_active += 1; stats["logging_active"] += 1
stats["logging_active"] += 1
else:
acc_stopped += 1; stats["logging_stopped"] += 1
stats["logging_stopped"] += 1

# Metric Aggregation
bucket = val.get("s3_bucket")
if bucket and bucket != "N/A":
stats["s3_buckets"].add(bucket)
Expand All @@ -86,20 +80,17 @@ def main():
stats["cw_bytes"] += val["cw_logs_size_bytes"]
retention_distribution[val.get("cw_logs_retention_days", "Never Expire")] += 1

# Print row for each trail found
print(f"{acc_id:<15} | {ou_path[:30]:<30} | {summary:<25} | {val.get('is_logging'):<15} | {trail_arn:<100}")
# Print row with Index
print(f"{idx:<5} | {acc_id:<15} | {ou_path[:35]:<35} | {summary:<25} | {val.get('is_logging'):<15} | {trail_arn:<100}")

# FOOTPRINT SUMMARY
s3_gb, cw_gb = stats["s3_bytes"] / (1024**3), stats["cw_bytes"] / (1024**3)

print("-" * report_width)
print(f"ORGANIZATION FOOTPRINT SUMMARY | Org ID: {org_id}")
print(f" Logging Status: {stats['logging_active']} Active | {stats['logging_stopped']} Stopped")
print(f" S3 Storage: {s3_gb:.2f} GB | {stats['s3_objects']:,} objects")
print(f" CloudWatch Logs: {cw_gb:.2f} GB | {len(stats['cw_group_arns'])} unique groups")
print(f" Primary (Home) Trails: {stats['total_home_regions']}")
print(f" Shadow Regions Covered: {stats['total_shadow_regions']}")
print(f" Total Regional Presence: {stats['total_home_regions'] + stats['total_shadow_regions']}")
print(f"ORGANIZATION CLOUDTRAIL FOOTPRINT SUMMARY | Org ID: {org_id}")
print(f" Total Accounts Found: {account_count}") # Added Account Count
print(f" Primary (Home) Trails: {stats['total_home_regions']}")
print(f" Shadow Regions Covered: {stats['total_shadow_regions']}")
print(f" S3 Storage Total: {s3_gb:.2f} GB")
print("-" * report_width)

if __name__ == "__main__":
Expand Down
29 changes: 15 additions & 14 deletions local-app/python-tools/cross-organization/assess_check_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
import glob

# --- VERSIONING ---
__version__ = "1.0.10"
__version__ = "1.0.11"

def find_latest_file(pattern):
"""Searches for the most recent file matching the pattern."""
files = glob.glob(pattern)
return max(files, key=os.path.getctime) if files else None

Expand All @@ -32,24 +31,26 @@ def main():
print(f"Error reading {input_file}: {e}"); sys.exit(1)

org_id = data[0].get("org_id", "Unknown") if data else "Unknown"
account_count = len(data)

print("-" * 140)
print("-" * 150)
print(f"AWS CONFIG ASSESSMENT | Org ID: {org_id} | Pattern: {args.central_bucket_regex}")
print("-" * 140)
print(f"{'Account ID':<15} | {'OU Path':<30} | {'Global Status':<12} | {'S3 Compliance'}")
print("-" * 140)
print("-" * 150)
# Added Index Column to Header
print(f"{'Idx':<5} | {'Account ID':<15} | {'OU Path':<35} | {'Global Status':<12} | {'S3 Compliance'}")
print("-" * 150)

stats = {
"objects": 0, "size_bytes": 0,
"total_recorders": 0,
"config_count_central": 0,
"config_count_non_central": 0,
"unique_central_buckets": set(),
"unique_non_central_buckets": set(),
"accounts": len(data)
"unique_non_central_buckets": set()
}

for account in data:
# Added enumerate to track Index
for idx, account in enumerate(data, 1):
acc_id = account.get("account_id")
ou_path = account.get("ou_path", "Root")
checks = account.get("data", {})
Expand All @@ -58,8 +59,6 @@ def main():
s3_issues = []
for reg, reg_data in checks.items():
if reg == "account_summary": continue

# Logic update: Verify resource type
if reg_data.get("resource") != "config": continue

if reg_data.get("recorder_status") == "ON":
Expand All @@ -79,16 +78,18 @@ def main():
s3_issues.append(bucket)

s3_status = "NON_COMPLIANT" if s3_issues else "COMPLIANT"
print(f"{acc_id:<15} | {ou_path[:30]:<30} | {summary:<12} | {s3_status}")
# Print with Index
print(f"{idx:<5} | {acc_id:<15} | {ou_path[:35]:<35} | {summary:<12} | {s3_status}")

size_gb = stats["size_bytes"] / (1024**3)
print("-" * 140)
print("-" * 150)
print(f"ORGANIZATION FOOTPRINT SUMMARY (CONFIG) | Org ID: {org_id}")
print(f" Total Accounts Found: {account_count}") # Added Account Count
print(f" Active Recorders Found: {stats['total_recorders']}")
print(f" Total S3 Storage: {size_gb:.2f} GB")
print(f" Configs using Central: {stats['config_count_central']}")
print(f" Configs using Non-Central:{stats['config_count_non_central']}")
print("-" * 140)
print("-" * 150)

if __name__ == "__main__":
main()

0 comments on commit 52e0177

Please sign in to comment.