runbooks 1.1.7__py3-none-any.whl → 1.1.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runbooks/__init__.py +1 -1
- runbooks/__init___optimized.py +2 -1
- runbooks/_platform/__init__.py +1 -1
- runbooks/cfat/cli.py +4 -3
- runbooks/cfat/cloud_foundations_assessment.py +1 -2
- runbooks/cfat/tests/test_cli.py +4 -1
- runbooks/cli/commands/finops.py +68 -19
- runbooks/cli/commands/inventory.py +838 -14
- runbooks/cli/commands/operate.py +65 -4
- runbooks/cli/commands/vpc.py +1 -1
- runbooks/cloudops/cost_optimizer.py +1 -3
- runbooks/common/cli_decorators.py +6 -4
- runbooks/common/config_loader.py +787 -0
- runbooks/common/config_schema.py +280 -0
- runbooks/common/dry_run_framework.py +14 -2
- runbooks/common/mcp_integration.py +238 -0
- runbooks/finops/ebs_cost_optimizer.py +7 -4
- runbooks/finops/elastic_ip_optimizer.py +7 -4
- runbooks/finops/infrastructure/__init__.py +3 -2
- runbooks/finops/infrastructure/commands.py +7 -4
- runbooks/finops/infrastructure/load_balancer_optimizer.py +7 -4
- runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +7 -4
- runbooks/finops/nat_gateway_optimizer.py +7 -4
- runbooks/finops/tests/run_tests.py +1 -1
- runbooks/inventory/ArgumentsClass.py +2 -1
- runbooks/inventory/CLAUDE.md +41 -0
- runbooks/inventory/README.md +210 -2
- runbooks/inventory/Tests/test_Inventory_Modules.py +27 -10
- runbooks/inventory/Tests/test_cfn_describe_stacks.py +18 -7
- runbooks/inventory/Tests/test_ec2_describe_instances.py +30 -15
- runbooks/inventory/Tests/test_lambda_list_functions.py +17 -3
- runbooks/inventory/Tests/test_org_list_accounts.py +17 -4
- runbooks/inventory/account_class.py +0 -1
- runbooks/inventory/all_my_instances_wrapper.py +4 -8
- runbooks/inventory/aws_organization.png +0 -0
- runbooks/inventory/check_cloudtrail_compliance.py +4 -4
- runbooks/inventory/check_controltower_readiness.py +50 -47
- runbooks/inventory/check_landingzone_readiness.py +35 -31
- runbooks/inventory/cloud_foundations_integration.py +8 -3
- runbooks/inventory/collectors/aws_compute.py +59 -11
- runbooks/inventory/collectors/aws_management.py +39 -5
- runbooks/inventory/core/collector.py +1655 -159
- runbooks/inventory/core/concurrent_paginator.py +511 -0
- runbooks/inventory/discovery.md +15 -6
- runbooks/inventory/{draw_org_structure.py → draw_org.py} +55 -9
- runbooks/inventory/drift_detection_cli.py +8 -68
- runbooks/inventory/find_cfn_drift_detection.py +14 -4
- runbooks/inventory/find_cfn_orphaned_stacks.py +7 -5
- runbooks/inventory/find_cfn_stackset_drift.py +5 -5
- runbooks/inventory/find_ec2_security_groups.py +6 -3
- runbooks/inventory/find_landingzone_versions.py +5 -5
- runbooks/inventory/find_vpc_flow_logs.py +5 -5
- runbooks/inventory/inventory.sh +20 -7
- runbooks/inventory/inventory_mcp_cli.py +4 -0
- runbooks/inventory/inventory_modules.py +9 -7
- runbooks/inventory/list_cfn_stacks.py +18 -8
- runbooks/inventory/list_cfn_stackset_operation_results.py +2 -2
- runbooks/inventory/list_cfn_stackset_operations.py +32 -20
- runbooks/inventory/list_cfn_stacksets.py +7 -4
- runbooks/inventory/list_config_recorders_delivery_channels.py +4 -4
- runbooks/inventory/list_ds_directories.py +3 -3
- runbooks/inventory/list_ec2_availability_zones.py +7 -3
- runbooks/inventory/list_ec2_ebs_volumes.py +3 -3
- runbooks/inventory/list_ec2_instances.py +1 -1
- runbooks/inventory/list_ecs_clusters_and_tasks.py +8 -4
- runbooks/inventory/list_elbs_load_balancers.py +7 -3
- runbooks/inventory/list_enis_network_interfaces.py +3 -3
- runbooks/inventory/list_guardduty_detectors.py +9 -5
- runbooks/inventory/list_iam_policies.py +7 -3
- runbooks/inventory/list_iam_roles.py +3 -3
- runbooks/inventory/list_iam_saml_providers.py +8 -4
- runbooks/inventory/list_lambda_functions.py +8 -4
- runbooks/inventory/list_org_accounts.py +306 -276
- runbooks/inventory/list_org_accounts_users.py +45 -9
- runbooks/inventory/list_rds_db_instances.py +4 -4
- runbooks/inventory/list_route53_hosted_zones.py +3 -3
- runbooks/inventory/list_servicecatalog_provisioned_products.py +5 -5
- runbooks/inventory/list_sns_topics.py +4 -4
- runbooks/inventory/list_ssm_parameters.py +6 -3
- runbooks/inventory/list_vpc_subnets.py +8 -4
- runbooks/inventory/list_vpcs.py +15 -4
- runbooks/inventory/mcp_inventory_validator.py +771 -134
- runbooks/inventory/mcp_vpc_validator.py +6 -0
- runbooks/inventory/organizations_discovery.py +17 -3
- runbooks/inventory/organizations_utils.py +553 -0
- runbooks/inventory/output_formatters.py +422 -0
- runbooks/inventory/recover_cfn_stack_ids.py +5 -5
- runbooks/inventory/run_on_multi_accounts.py +3 -3
- runbooks/inventory/tag_coverage.py +481 -0
- runbooks/inventory/validation_utils.py +358 -0
- runbooks/inventory/verify_ec2_security_groups.py +18 -5
- runbooks/inventory/vpc_architecture_validator.py +7 -1
- runbooks/inventory/vpc_dependency_analyzer.py +6 -0
- runbooks/main_final.py +2 -2
- runbooks/main_ultra_minimal.py +2 -2
- runbooks/mcp/integration.py +6 -4
- runbooks/remediation/acm_remediation.py +2 -2
- runbooks/remediation/cloudtrail_remediation.py +2 -2
- runbooks/remediation/cognito_remediation.py +2 -2
- runbooks/remediation/dynamodb_remediation.py +2 -2
- runbooks/remediation/ec2_remediation.py +2 -2
- runbooks/remediation/kms_remediation.py +2 -2
- runbooks/remediation/lambda_remediation.py +2 -2
- runbooks/remediation/rds_remediation.py +2 -2
- runbooks/remediation/s3_remediation.py +1 -1
- runbooks/vpc/cloudtrail_audit_integration.py +1 -1
- {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/METADATA +74 -4
- {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/RECORD +112 -105
- runbooks/__init__.py.backup +0 -134
- {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/WHEEL +0 -0
- {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/top_level.txt +0 -0
@@ -76,7 +76,7 @@ class ManagementResourceCollector(BaseResourceCollector):
|
|
76
76
|
|
77
77
|
try:
|
78
78
|
if resource_type.startswith("organizations:"):
|
79
|
-
resources.extend(self._collect_organizations_resources(clients, context, resource_type))
|
79
|
+
resources.extend(self._collect_organizations_resources(clients, context, resource_type, resource_filters))
|
80
80
|
elif resource_type.startswith("cloudformation:"):
|
81
81
|
resources.extend(self._collect_cloudformation_resources(clients, context, resource_type))
|
82
82
|
elif resource_type.startswith("servicecatalog:"):
|
@@ -107,15 +107,17 @@ class ManagementResourceCollector(BaseResourceCollector):
|
|
107
107
|
}
|
108
108
|
|
109
109
|
def _collect_organizations_resources(
|
110
|
-
self, clients: Dict[str, Any], context: CollectionContext, resource_type: str
|
110
|
+
self, clients: Dict[str, Any], context: CollectionContext, resource_type: str,
|
111
|
+
resource_filters: Optional[Dict[str, Any]] = None
|
111
112
|
) -> List[AWSResource]:
|
112
113
|
"""Collect AWS Organizations resources."""
|
113
114
|
resources = []
|
115
|
+
resource_filters = resource_filters or {}
|
114
116
|
org_client = clients["organizations"]
|
115
117
|
|
116
118
|
try:
|
117
119
|
if resource_type == "organizations:account":
|
118
|
-
resources.extend(self._collect_organization_accounts(org_client, context))
|
120
|
+
resources.extend(self._collect_organization_accounts(org_client, context, resource_filters))
|
119
121
|
elif resource_type == "organizations:organizational_unit":
|
120
122
|
resources.extend(self._collect_organizational_units(org_client, context))
|
121
123
|
elif resource_type == "organizations:policy":
|
@@ -130,14 +132,44 @@ class ManagementResourceCollector(BaseResourceCollector):
|
|
130
132
|
return resources
|
131
133
|
|
132
134
|
@aws_api_retry
|
133
|
-
def _collect_organization_accounts(self, org_client, context: CollectionContext
|
134
|
-
|
135
|
+
def _collect_organization_accounts(self, org_client, context: CollectionContext,
|
136
|
+
resource_filters: Optional[Dict[str, Any]] = None) -> List[AWSResource]:
|
137
|
+
"""
|
138
|
+
Collect organization accounts with optional root-only filtering.
|
139
|
+
|
140
|
+
Args:
|
141
|
+
org_client: boto3 Organizations client
|
142
|
+
context: Collection context
|
143
|
+
resource_filters: Optional filters including 'root_only' for management account filtering
|
144
|
+
|
145
|
+
Returns:
|
146
|
+
List of organization account resources
|
147
|
+
"""
|
135
148
|
resources = []
|
149
|
+
resource_filters = resource_filters or {}
|
150
|
+
root_only = resource_filters.get("root_only", False)
|
136
151
|
|
137
152
|
try:
|
153
|
+
# Get management account ID if root-only filter is active
|
154
|
+
management_account_id = None
|
155
|
+
if root_only:
|
156
|
+
try:
|
157
|
+
org_info = org_client.describe_organization()
|
158
|
+
management_account_id = org_info["Organization"]["MasterAccountId"]
|
159
|
+
logger.info(f"root-only filter active: Management account ID = {management_account_id}")
|
160
|
+
except Exception as e:
|
161
|
+
logger.warning(f"Could not retrieve management account ID for root-only filter: {e}")
|
162
|
+
root_only = False # Disable filter if retrieval fails
|
163
|
+
|
164
|
+
# Collect accounts with filtering
|
138
165
|
paginator = org_client.get_paginator("list_accounts")
|
139
166
|
for page in paginator.paginate():
|
140
167
|
for account in page.get("Accounts", []):
|
168
|
+
# Apply root-only filter if active
|
169
|
+
if root_only and account["Id"] != management_account_id:
|
170
|
+
logger.debug(f"Skipping non-management account: {account['Id']} (root-only filter)")
|
171
|
+
continue # Skip non-management accounts
|
172
|
+
|
141
173
|
resource = AWSResource(
|
142
174
|
resource_id=account["Id"],
|
143
175
|
resource_type="organizations:account",
|
@@ -157,6 +189,8 @@ class ManagementResourceCollector(BaseResourceCollector):
|
|
157
189
|
)
|
158
190
|
resources.append(resource)
|
159
191
|
|
192
|
+
logger.debug(f"Collected {len(resources)} organization accounts (root_only: {root_only})")
|
193
|
+
|
160
194
|
except Exception as e:
|
161
195
|
logger.error(f"Error collecting organization accounts: {e}")
|
162
196
|
|