Skip to content

Commit

Permalink
update 1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Jan 2, 2026
1 parent 3ad15a0 commit bf9eb11
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 38 deletions.
78 changes: 49 additions & 29 deletions local-app/python-tools/cross-organization/check_config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
def account_task(account_session, account_id, account_name, region):
"""
Task: Deep Audit of AWS Config across all regions.
Returns: Data structured by region for JSON/CSV processing.
"""
results = {"alias": "None", "status": "SUCCESS", "data": {}}
import re
from datetime import datetime, timedelta

def get_s3_metrics(session, bucket_name, region):
"""Fetches NumberOfObjects and BucketSizeBytes from CloudWatch."""
cw = session.client('cloudwatch', region_name=region)
metrics = {"bucket_size_bytes": 0, "object_count": 0}

end = datetime.utcnow()
start = end - timedelta(days=2)

try:
for metric_name in ['BucketSizeBytes', 'NumberOfObjects']:
response = cw.get_metric_statistics(
Namespace='AWS/S3',
MetricName=metric_name,
Dimensions=[
{'Name': 'BucketName', 'Value': bucket_name},
{'Name': 'StorageType', 'Value': 'StandardStorage'}
],
StartTime=start,
EndTime=end,
Period=86400,
Statistics=['Average']
)

if response['Datapoints']:
key = "bucket_size_bytes" if metric_name == 'BucketSizeBytes' else "object_count"
metrics[key] = int(response['Datapoints'][-1]['Average'])
except:
pass # Return 0s if metrics fail (e.g., bucket in different region)
return metrics

def account_task(account_session, account_id, account_name, region, bucket_regex=".*"):
results = {"alias": "None", "data": {}}

try:
iam = account_session.client('iam')
Expand All @@ -15,37 +44,28 @@ def account_task(account_session, account_id, account_name, region):

for reg in regions:
config = account_session.client('config', region_name=reg)
channels = config.describe_delivery_channels().get('DeliveryChannels', [])

# Fetch Config state
recorders = config.describe_configuration_recorders().get('ConfigurationRecorders', [])
delivery = config.describe_delivery_channels().get('DeliveryChannels', [])
retention = config.describe_retention_configurations().get('RetentionConfigurations', [])

# Store regional metrics
reg_data = {
"recorder_enabled": "False",
"global_resources": "False",
"s3_bucket": "N/A",
"sns_topic": "N/A",
"delivery_freq": "N/A",
"retention_days": "2555 (7yr)"
"bucket_regex_match": "N/A",
"bucket_size_bytes": 0,
"object_count": 0
}

if recorders:
reg_data["recorder_enabled"] = "True"
reg_data["global_resources"] = str(recorders[0].get('recordingGroup', {}).get('includeGlobalResourceTypes', False))

if delivery:
reg_data["s3_bucket"] = delivery[0].get('s3BucketName', 'N/A')
reg_data["sns_topic"] = delivery[0].get('snsTopicARN', 'N/A').split(':')[-1]
reg_data["delivery_freq"] = delivery[0].get('configSnapshotDeliveryProperties', {}).get('deliveryFrequency', '24h')

if retention:
reg_data["retention_days"] = str(retention[0].get('RetentionPeriodInDays'))
if channels:
bucket = channels[0].get('s3BucketName', 'N/A')
reg_data["s3_bucket"] = bucket
reg_data["bucket_regex_match"] = str(bool(re.match(bucket_regex, bucket)))

# Fetch metrics if bucket exists
if bucket != "N/A":
metrics = get_s3_metrics(account_session, bucket, reg)
reg_data.update(metrics)

results["data"][reg] = reg_data

except Exception as e:
results["status"] = f"ERROR: {str(e)}"
results["error"] = str(e)

return results
17 changes: 8 additions & 9 deletions local-app/python-tools/cross-organization/org_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@
import json
import csv
import time
import re
import importlib
from datetime import datetime
from pathlib import Path

# --- VERSIONING ---
__version__ = "1.3.0"
__version__ = "1.4.0"

class OrgTaskRunner:
def __init__(self, args):
self.args = args
self.output_log = []
self.full_results = [] # Internal list of dicts for JSON/CSV
self.full_results = []
self.hierarchy_cache = {}
self.start_time = 0
self.org_id = "unknown"
Expand All @@ -37,7 +38,6 @@ def run(self):
self.org_id = org.describe_organization()['Organization']['Id']
except: pass

# Load dynamic tasks
tasks = []
if self.args.enable_checks:
sys.path.append(os.getcwd())
Expand All @@ -52,7 +52,7 @@ def run(self):

all_accounts.sort(key=lambda x: x['Name' if self.args.sort == 'name' else 'Id'].lower())

self.log_print(f"--- Starting Org Run (v{__version__}) | Accounts: {len(all_accounts)} ---")
self.log_print(f"--- Org Run v{__version__} | Regex: {self.args.central_bucket_regex} ---")

for i, acc in enumerate(all_accounts, 1):
acc_id, acc_name = acc['Id'], acc['Name']
Expand All @@ -70,10 +70,10 @@ def run(self):
account_data = {"account_id": acc_id, "account_name": acc_name, "checks": {}}

for t_func in tasks:
# Capture raw data from task
res = t_func(m_sess, acc_id, acc_name, self.args.region)
# Pass the regex to the task function
res = t_func(m_sess, acc_id, acc_name, self.args.region, self.args.central_bucket_regex)
account_data["alias"] = res.get("alias")
account_data["checks"] = res.get("data", {}) # Expecting a dict of regions
account_data["checks"] = res.get("data", {})

self.full_results.append(account_data)
self.log_print(f"[{i}/{len(all_accounts)}] Processed {acc_name}")
Expand All @@ -86,11 +86,9 @@ def run(self):
ds = datetime.now().strftime("%Y-%m-%dT%H%M%S")
base = self.args.output if self.args.output != 'DEFAULT' else f"audit_{self.org_id}"

# 1. Save JSON
with open(f"{base}.{ds}.json", 'w') as f:
json.dump(self.full_results, f, indent=2)

# 2. Save CSV (Long Format)
with open(f"{base}.{ds}.csv", 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(["account_id", "account_alias", "region", "field_name", "field_value"])
Expand All @@ -109,4 +107,5 @@ def run(self):
p.add_argument("--sort", choices=['id', 'name'], default='name')
p.add_argument("--output", nargs='?', const='DEFAULT')
p.add_argument("--enable-checks", nargs='+')
p.add_argument("--central-bucket-regex", default=".*", help="Regex to validate Config S3 buckets")
OrgTaskRunner(p.parse_args()).run()

0 comments on commit bf9eb11

Please sign in to comment.