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.
Files changed (113) hide show
  1. runbooks/__init__.py +1 -1
  2. runbooks/__init___optimized.py +2 -1
  3. runbooks/_platform/__init__.py +1 -1
  4. runbooks/cfat/cli.py +4 -3
  5. runbooks/cfat/cloud_foundations_assessment.py +1 -2
  6. runbooks/cfat/tests/test_cli.py +4 -1
  7. runbooks/cli/commands/finops.py +68 -19
  8. runbooks/cli/commands/inventory.py +838 -14
  9. runbooks/cli/commands/operate.py +65 -4
  10. runbooks/cli/commands/vpc.py +1 -1
  11. runbooks/cloudops/cost_optimizer.py +1 -3
  12. runbooks/common/cli_decorators.py +6 -4
  13. runbooks/common/config_loader.py +787 -0
  14. runbooks/common/config_schema.py +280 -0
  15. runbooks/common/dry_run_framework.py +14 -2
  16. runbooks/common/mcp_integration.py +238 -0
  17. runbooks/finops/ebs_cost_optimizer.py +7 -4
  18. runbooks/finops/elastic_ip_optimizer.py +7 -4
  19. runbooks/finops/infrastructure/__init__.py +3 -2
  20. runbooks/finops/infrastructure/commands.py +7 -4
  21. runbooks/finops/infrastructure/load_balancer_optimizer.py +7 -4
  22. runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +7 -4
  23. runbooks/finops/nat_gateway_optimizer.py +7 -4
  24. runbooks/finops/tests/run_tests.py +1 -1
  25. runbooks/inventory/ArgumentsClass.py +2 -1
  26. runbooks/inventory/CLAUDE.md +41 -0
  27. runbooks/inventory/README.md +210 -2
  28. runbooks/inventory/Tests/test_Inventory_Modules.py +27 -10
  29. runbooks/inventory/Tests/test_cfn_describe_stacks.py +18 -7
  30. runbooks/inventory/Tests/test_ec2_describe_instances.py +30 -15
  31. runbooks/inventory/Tests/test_lambda_list_functions.py +17 -3
  32. runbooks/inventory/Tests/test_org_list_accounts.py +17 -4
  33. runbooks/inventory/account_class.py +0 -1
  34. runbooks/inventory/all_my_instances_wrapper.py +4 -8
  35. runbooks/inventory/aws_organization.png +0 -0
  36. runbooks/inventory/check_cloudtrail_compliance.py +4 -4
  37. runbooks/inventory/check_controltower_readiness.py +50 -47
  38. runbooks/inventory/check_landingzone_readiness.py +35 -31
  39. runbooks/inventory/cloud_foundations_integration.py +8 -3
  40. runbooks/inventory/collectors/aws_compute.py +59 -11
  41. runbooks/inventory/collectors/aws_management.py +39 -5
  42. runbooks/inventory/core/collector.py +1655 -159
  43. runbooks/inventory/core/concurrent_paginator.py +511 -0
  44. runbooks/inventory/discovery.md +15 -6
  45. runbooks/inventory/{draw_org_structure.py → draw_org.py} +55 -9
  46. runbooks/inventory/drift_detection_cli.py +8 -68
  47. runbooks/inventory/find_cfn_drift_detection.py +14 -4
  48. runbooks/inventory/find_cfn_orphaned_stacks.py +7 -5
  49. runbooks/inventory/find_cfn_stackset_drift.py +5 -5
  50. runbooks/inventory/find_ec2_security_groups.py +6 -3
  51. runbooks/inventory/find_landingzone_versions.py +5 -5
  52. runbooks/inventory/find_vpc_flow_logs.py +5 -5
  53. runbooks/inventory/inventory.sh +20 -7
  54. runbooks/inventory/inventory_mcp_cli.py +4 -0
  55. runbooks/inventory/inventory_modules.py +9 -7
  56. runbooks/inventory/list_cfn_stacks.py +18 -8
  57. runbooks/inventory/list_cfn_stackset_operation_results.py +2 -2
  58. runbooks/inventory/list_cfn_stackset_operations.py +32 -20
  59. runbooks/inventory/list_cfn_stacksets.py +7 -4
  60. runbooks/inventory/list_config_recorders_delivery_channels.py +4 -4
  61. runbooks/inventory/list_ds_directories.py +3 -3
  62. runbooks/inventory/list_ec2_availability_zones.py +7 -3
  63. runbooks/inventory/list_ec2_ebs_volumes.py +3 -3
  64. runbooks/inventory/list_ec2_instances.py +1 -1
  65. runbooks/inventory/list_ecs_clusters_and_tasks.py +8 -4
  66. runbooks/inventory/list_elbs_load_balancers.py +7 -3
  67. runbooks/inventory/list_enis_network_interfaces.py +3 -3
  68. runbooks/inventory/list_guardduty_detectors.py +9 -5
  69. runbooks/inventory/list_iam_policies.py +7 -3
  70. runbooks/inventory/list_iam_roles.py +3 -3
  71. runbooks/inventory/list_iam_saml_providers.py +8 -4
  72. runbooks/inventory/list_lambda_functions.py +8 -4
  73. runbooks/inventory/list_org_accounts.py +306 -276
  74. runbooks/inventory/list_org_accounts_users.py +45 -9
  75. runbooks/inventory/list_rds_db_instances.py +4 -4
  76. runbooks/inventory/list_route53_hosted_zones.py +3 -3
  77. runbooks/inventory/list_servicecatalog_provisioned_products.py +5 -5
  78. runbooks/inventory/list_sns_topics.py +4 -4
  79. runbooks/inventory/list_ssm_parameters.py +6 -3
  80. runbooks/inventory/list_vpc_subnets.py +8 -4
  81. runbooks/inventory/list_vpcs.py +15 -4
  82. runbooks/inventory/mcp_inventory_validator.py +771 -134
  83. runbooks/inventory/mcp_vpc_validator.py +6 -0
  84. runbooks/inventory/organizations_discovery.py +17 -3
  85. runbooks/inventory/organizations_utils.py +553 -0
  86. runbooks/inventory/output_formatters.py +422 -0
  87. runbooks/inventory/recover_cfn_stack_ids.py +5 -5
  88. runbooks/inventory/run_on_multi_accounts.py +3 -3
  89. runbooks/inventory/tag_coverage.py +481 -0
  90. runbooks/inventory/validation_utils.py +358 -0
  91. runbooks/inventory/verify_ec2_security_groups.py +18 -5
  92. runbooks/inventory/vpc_architecture_validator.py +7 -1
  93. runbooks/inventory/vpc_dependency_analyzer.py +6 -0
  94. runbooks/main_final.py +2 -2
  95. runbooks/main_ultra_minimal.py +2 -2
  96. runbooks/mcp/integration.py +6 -4
  97. runbooks/remediation/acm_remediation.py +2 -2
  98. runbooks/remediation/cloudtrail_remediation.py +2 -2
  99. runbooks/remediation/cognito_remediation.py +2 -2
  100. runbooks/remediation/dynamodb_remediation.py +2 -2
  101. runbooks/remediation/ec2_remediation.py +2 -2
  102. runbooks/remediation/kms_remediation.py +2 -2
  103. runbooks/remediation/lambda_remediation.py +2 -2
  104. runbooks/remediation/rds_remediation.py +2 -2
  105. runbooks/remediation/s3_remediation.py +1 -1
  106. runbooks/vpc/cloudtrail_audit_integration.py +1 -1
  107. {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/METADATA +74 -4
  108. {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/RECORD +112 -105
  109. runbooks/__init__.py.backup +0 -134
  110. {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/WHEEL +0 -0
  111. {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/entry_points.txt +0 -0
  112. {runbooks-1.1.7.dist-info → runbooks-1.1.10.dist-info}/licenses/LICENSE +0 -0
  113. {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) -> List[AWSResource]:
134
- """Collect organization accounts."""
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