From f1d0854273c7a462efd6b008086829c74df054ae Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 13 Jan 2026 11:58:52 -0500 Subject: [PATCH] restore age table --- .../cross-organization/assess_check_ecr.py | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/local-app/python-tools/cross-organization/assess_check_ecr.py b/local-app/python-tools/cross-organization/assess_check_ecr.py index 714eeb82..0952054b 100755 --- a/local-app/python-tools/cross-organization/assess_check_ecr.py +++ b/local-app/python-tools/cross-organization/assess_check_ecr.py @@ -4,7 +4,7 @@ from collections import Counter, defaultdict # --- VERSIONING --- -__version__ = "1.3.5" +__version__ = "1.3.6" def find_latest_file(pattern): """Locates the most recent file matching the given pattern.""" @@ -29,18 +29,15 @@ def bucket_age(days, counters): else: counters['<30'] += 1 def main(): - parser = argparse.ArgumentParser(description="ECR Full Spectrum Assessor & Reporter - v1.3.5") + parser = argparse.ArgumentParser(description="ECR Full Spectrum Assessor & Reporter - v1.3.6") parser.add_argument("--input", help="JSON audit file") args = parser.parse_args() - # FIX: Pass the required 'pattern' argument to the function call search_pattern = "audit_results.check_ecr.*.json" input_file = args.input or find_latest_file(search_pattern) - if not input_file: print(f"Error: No file found matching {search_pattern}"); sys.exit(1) - # Generate the output filename for the results file base_name, _ = os.path.splitext(input_file) output_file = f"{base_name}_results.txt" @@ -115,10 +112,23 @@ def report_print(msg=""): report_print("-" * report_width) report_print(f"ORGANIZATION ECR SUMMARY\n") + report_print(f" --- Config & Storage ---") + report_print(f" Repos: {stats['total_repos']} ({stats['mut']['IMMUTABLE']} Immutable / {stats['mut']['MUTABLE']} Mutable) | Missing Lifecycle: {stats['no_lc']}") report_print(f" Total Data: {stats['total_bytes']/(1024**3):.2f} GB | Average Image Size: {avg_img_mb:.2f} MB") - report_print(f" Security: " + " | ".join([f"{s}: {stats['org_vulns'][s]:,}" for s in ["CRITICAL", "HIGH", "MEDIUM"]])) - - # DUPLICATE IMAGE AUDIT SUMMARY + + report_print(f"\n --- Security & Vulnerabilities ---") + report_print(f" Scan Coverage: {stats['scanned_imgs']} of {stats['total_images']} images scanned") + report_print(f" Org Totals: " + " | ".join([f"{s}: {stats['org_vulns'][s]:,}" for s in ["CRITICAL", "HIGH", "MEDIUM"]])) + + # RESTORED: Age Distribution Table + report_print(f"\n --- Age Distribution (Days since Push vs Pull) ---") + report_print(f" Average Image Age: {avg_push_age:.1f} days") + report_print(f" Bucket | Pushed Count | Pulled Count") + report_print(f" ----------- | ------------ | ------------") + for b in ['<30', '30-59', '60-89', '90-179', '180-364', '365+']: + report_print(f" {b:<11} | {stats['push_ages'][b]:<12} | {stats['pull_ages'][b]}") + + # Duplicate Image Audit Summary duplicates = {d: c for d, c in digest_tracker.items() if c > 1} report_print(f"\n --- Duplicate Image Audit ---") report_print(f" Total Duplicated Instances: {sum(duplicates.values())} across {len(duplicates)} unique digests")