Skip to content

Commit

Permalink
update readme, add config check
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Dec 31, 2025
1 parent 789c260 commit 1a30035
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
96 changes: 96 additions & 0 deletions local-app/python-tools/test-cross-organization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# README: AWS Organization Task Runner

## Overview

The `org_runner.py` is a modular Python utility designed to execute administrative tasks across every account in an AWS Organization. It handles the heavy lifting of:

1. **Identity Management**: Discovering partition (Commercial vs GovCloud) and Management account info.
2. **Hierarchy Discovery**: Resolving the full Organizational Unit (OU) path (e.g., `Production:Finance:Workloads`).
3. **Cross-Account Access**: Automating the `STS AssumeRole` workflow.
4. **Reporting**: Generating console tables, summary statistics by OU, and timestamped log files.

## Configuration

### Prerequisites

* **IAM Role**: A cross-account IAM role (e.g., `OrganizationAdminAccessRole`) must exist in all member accounts with a Trust Policy allowing your Management identity to assume it.
* **Permissions**: Your local credentials must have `organizations:List*` and `sts:AssumeRole` permissions.

### Modular Tasks

The script is designed for extensibility. To run a specific task (e.g., checking for unencrypted S3 buckets), simply modify the `account_task` function:

```python
def account_task(account_session, account_id, account_name, region):
s3 = account_session.client('s3')
# Your custom logic here...
return {"status": "SUCCESS", "alias": "some-data"}

```

## Usage

### Make Executable

```bash
chmod +x org_runner.py

```

### Run a Connectivity Test

```bash
./org_runner.py --role-name MyCrossAccountRole --output

```

### Command Line Arguments

| Argument | Description | Default |
| --- | --- | --- |
| `--role-name` | **Required**. The name of the IAM role to assume in member accounts. | N/A |
| `--profile` | The AWS CLI profile to use for the management session. | `AWS_PROFILE` env var |
| `--region` | The base region for API calls. | `us-east-1` |
| `--output` | Save results to a file. Auto-generates `results_ORGID.ISO-DATE.txt` if no name provided. | None |
| `--sort` | Sort the table by `name` or `id`. | `name` |
| `--debug` | Enables Boto3 HTTP wire-trace logging. | False |

## Security Best Practices

* **Least Privilege**: Ensure the `account_task` only uses the clients it needs.
* **Audit Trails**: Use the `--output` flag to maintain a record of administrative actions taken across the Org.
* **Error Handling**: The script uses a `try/except` block per account, ensuring that one failed `AssumeRole` doesn't crash the entire organization-wide run.

### Utility Capability Overview

The current version of the utility provides a production-ready framework with the following capabilities:

* **Identity-Aware Execution**: Automatically detects if it's running in standard AWS, GovCloud, or China partitions and adjusts ARN construction.
* **Intelligent Hierarchy Mapping**: Understands the full logical path of every account, allowing you to see which Business Units are failing or succeeding.
* **Safe Automation**: Uses `AssumeRole` with short-lived credentials; no static secrets are stored.
* **High Scannability**: Specifically designed for large-scale organizations (hundreds of accounts) with sorted tables and summary counts.
* **Audit-Ready Logging**: Generates timestamped, Organization-specific files that capture every line of output, including configuration headers and execution time.
* **Extensible Engine**: By separating the "loop" logic from the "task" logic, it can be repurposed for security audits, cost remediation, or resource inventory in minutes.

# CHANGELOG

This table tracks the development of the tool based on your iterative requirements.

| Version | Focus | Key Features Added |
| --- | --- | --- |
| **1.1.0** | Framework | Refactored into a **Modular Wrapper** with a standalone `account_task` function. |
| **1.0.21** | Automation | Implemented **Dynamic Naming**: `results_{org_id}.{ISO-date}.txt`. |
| **1.0.19** | Optimization | Refactored logging to a list-buffer to remove class complexity and delay file writes. |
| **1.0.18** | Persistence | Added `--output` flag and `Tee` class for dual console/file logging. |
| **1.0.17** | Performance | Added `time.perf_counter()` to provide total elapsed time in the summary. |
| **1.0.16** | Formatting | Expanded Alias field to 64 chars to prevent truncation of long IAM aliases. |
| **1.0.15** | Metadata | Included OU IDs in the summary table for precise infrastructure mapping. |
| **1.0.14** | Reporting | Added **Summary Table** at the end and stripped "Root" from OU path labels. |
| **1.0.13** | Logic Fix | Fixed OU path "accumulation bug" by implementing ID-based path caching. |
| **1.0.12** | Hierarchy | Implemented recursive OU path lookup (e.g., `Prod:App:DB`). |
| **1.0.11** | Sorting | Added `--sort [id|name]` and item numbering for long output lists. |
| **1.0.10** | Diagnostics | Added `--debug` flag for Boto3 wire-trace and removed emojis for log compatibility. |
| **1.0.9** | Partitioning | Added **Partition Awareness** to handle Commercial vs GovCloud (`arn:aws` vs `arn:aws-us-gov`). |
| **1.0.5** | Org Support | Added `organizations:ListAccounts` to loop through all active accounts. |
| **1.0.0** | Initial Script | Basic STS AssumeRole logic for a single account. |

36 changes: 36 additions & 0 deletions local-app/python-tools/test-cross-organization/config_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
def config_check_account_task(account_session, account_id, account_name, region):
"""
Task: Checks for AWS Config Recorders in the specified region.
Identifies if 'IncludeGlobalResourceTypes' is enabled (potential cost/duplication).
"""
results = {"alias": "None", "status": "SUCCESS", "details": ""}

try:
# 1. Get IAM Alias for reporting
iam = account_session.client('iam')
aliases = iam.list_account_aliases().get('AccountAliases', [])
results["alias"] = aliases[0] if aliases else "None"

# 2. Check AWS Config Recorder
config = account_session.client('config', region_name=region)
recorders = config.describe_configuration_recorders().get('ConfigurationRecorders', [])

if not recorders:
results["status"] = "WARNING(NoRecorder)"
else:
# Check for Global Resource recording
for r in recorders:
group = r.get('recordingGroup', {})
if group.get('includeGlobalResourceTypes'):
results["status"] = "ACTION_REQ"
results["details"] = "GlobalResources:True"
else:
results["status"] = "OPTIMIZED"
results["details"] = "GlobalResources:False"

except ClientError as e:
results["status"] = f"FAIL({e.response['Error']['Code']})"
except Exception as e:
results["status"] = f"FAIL(Error)"

return results

0 comments on commit 1a30035

Please sign in to comment.