terraback 0.0.0__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 (239) hide show
  1. terraback/__init__.py +1 -0
  2. terraback/cli/__init__.py +0 -0
  3. terraback/cli/aws/__init__.py +390 -0
  4. terraback/cli/aws/acm/__init__.py +53 -0
  5. terraback/cli/aws/acm/certificates.py +117 -0
  6. terraback/cli/aws/apigateway/__init__.py +27 -0
  7. terraback/cli/aws/apigateway/rest_apis.py +341 -0
  8. terraback/cli/aws/autoscaling/__init__.py +107 -0
  9. terraback/cli/aws/autoscaling/auto_scaling_groups.py +64 -0
  10. terraback/cli/aws/autoscaling/launch_configurations.py +64 -0
  11. terraback/cli/aws/autoscaling/scaling_policies.py +91 -0
  12. terraback/cli/aws/cloudfront/__init__.py +139 -0
  13. terraback/cli/aws/cloudfront/cache_policies.py +94 -0
  14. terraback/cli/aws/cloudfront/distributions.py +220 -0
  15. terraback/cli/aws/cloudfront/origin_access_controls.py +74 -0
  16. terraback/cli/aws/cloudfront/origin_request_policies.py +84 -0
  17. terraback/cli/aws/cloudwatch/__init__.py +103 -0
  18. terraback/cli/aws/cloudwatch/alarms.py +80 -0
  19. terraback/cli/aws/cloudwatch/dashboards.py +63 -0
  20. terraback/cli/aws/cloudwatch/log_groups.py +52 -0
  21. terraback/cli/aws/ec2/__init__.py +121 -0
  22. terraback/cli/aws/ec2/amis.py +42 -0
  23. terraback/cli/aws/ec2/instances.py +42 -0
  24. terraback/cli/aws/ec2/key_pairs.py +31 -0
  25. terraback/cli/aws/ec2/launch_templates.py +34 -0
  26. terraback/cli/aws/ec2/network_interfaces.py +34 -0
  27. terraback/cli/aws/ec2/snapshots.py +31 -0
  28. terraback/cli/aws/ec2/volumes.py +34 -0
  29. terraback/cli/aws/ecr/__init__.py +45 -0
  30. terraback/cli/aws/ecr/repositories.py +95 -0
  31. terraback/cli/aws/ecs/__init__.py +125 -0
  32. terraback/cli/aws/ecs/clusters.py +111 -0
  33. terraback/cli/aws/ecs/services.py +186 -0
  34. terraback/cli/aws/ecs/task_definitions.py +244 -0
  35. terraback/cli/aws/efs/__init__.py +116 -0
  36. terraback/cli/aws/efs/access_points.py +88 -0
  37. terraback/cli/aws/efs/file_systems.py +90 -0
  38. terraback/cli/aws/efs/mount_targets.py +65 -0
  39. terraback/cli/aws/eips/__init__.py +35 -0
  40. terraback/cli/aws/eips/addresses.py +22 -0
  41. terraback/cli/aws/elasticache/__init__.py +176 -0
  42. terraback/cli/aws/elasticache/memcached_clusters.py +117 -0
  43. terraback/cli/aws/elasticache/parameter_groups.py +99 -0
  44. terraback/cli/aws/elasticache/redis_clusters.py +114 -0
  45. terraback/cli/aws/elasticache/replication_groups.py +127 -0
  46. terraback/cli/aws/elasticache/subnet_groups.py +84 -0
  47. terraback/cli/aws/elb/__init__.py +36 -0
  48. terraback/cli/aws/elb/classic_load_balancers.py +37 -0
  49. terraback/cli/aws/elbv2/__init__.py +234 -0
  50. terraback/cli/aws/elbv2/classic_load_balancers.py +37 -0
  51. terraback/cli/aws/elbv2/listener_rules.py +131 -0
  52. terraback/cli/aws/elbv2/listeners.py +64 -0
  53. terraback/cli/aws/elbv2/load_balancers.py +77 -0
  54. terraback/cli/aws/elbv2/ssl_policies.py +118 -0
  55. terraback/cli/aws/elbv2/target_group_attachments.py +107 -0
  56. terraback/cli/aws/elbv2/target_groups.py +61 -0
  57. terraback/cli/aws/elbv2/waf_associations.py +84 -0
  58. terraback/cli/aws/iam/__init__.py +36 -0
  59. terraback/cli/aws/iam/policies.py +39 -0
  60. terraback/cli/aws/iam/roles.py +25 -0
  61. terraback/cli/aws/lambda_func/__init__.py +60 -0
  62. terraback/cli/aws/lambda_func/functions.py +60 -0
  63. terraback/cli/aws/lambda_func/layers.py +108 -0
  64. terraback/cli/aws/rds/__init__.py +102 -0
  65. terraback/cli/aws/rds/instances.py +33 -0
  66. terraback/cli/aws/rds/parameter_groups.py +43 -0
  67. terraback/cli/aws/rds/subnet_groups.py +33 -0
  68. terraback/cli/aws/route53/__init__.py +58 -0
  69. terraback/cli/aws/route53/records.py +73 -0
  70. terraback/cli/aws/route53/zones.py +34 -0
  71. terraback/cli/aws/s3/__init__.py +33 -0
  72. terraback/cli/aws/s3/buckets.py +54 -0
  73. terraback/cli/aws/secretsmanager/__init__.py +89 -0
  74. terraback/cli/aws/secretsmanager/secret_versions.py +103 -0
  75. terraback/cli/aws/secretsmanager/secrets.py +186 -0
  76. terraback/cli/aws/session.py +35 -0
  77. terraback/cli/aws/sns/__init__.py +86 -0
  78. terraback/cli/aws/sns/sqs.py +75 -0
  79. terraback/cli/aws/sns/subscriptions.py +174 -0
  80. terraback/cli/aws/sns/topics.py +145 -0
  81. terraback/cli/aws/sqs/__init__.py +84 -0
  82. terraback/cli/aws/sqs/dead_letter_queues.py +63 -0
  83. terraback/cli/aws/sqs/queues.py +166 -0
  84. terraback/cli/aws/sqs/sqs.py +160 -0
  85. terraback/cli/aws/ssm/__init__.py +119 -0
  86. terraback/cli/aws/ssm/documents.py +203 -0
  87. terraback/cli/aws/ssm/maintenance_windows.py +161 -0
  88. terraback/cli/aws/ssm/parameters.py +180 -0
  89. terraback/cli/aws/vpc/__init__.py +201 -0
  90. terraback/cli/aws/vpc/internet_gateways.py +62 -0
  91. terraback/cli/aws/vpc/nat_gateways.py +67 -0
  92. terraback/cli/aws/vpc/route_tables.py +98 -0
  93. terraback/cli/aws/vpc/security_groups.py +24 -0
  94. terraback/cli/aws/vpc/subnets.py +21 -0
  95. terraback/cli/aws/vpc/vpc_endpoints.py +103 -0
  96. terraback/cli/aws/vpc/vpcs.py +21 -0
  97. terraback/cli/azure/__init__.py +172 -0
  98. terraback/cli/azure/compute/__init__.py +91 -0
  99. terraback/cli/azure/compute/disks.py +221 -0
  100. terraback/cli/azure/compute/ssh_keys.py +16 -0
  101. terraback/cli/azure/compute/virtual_machines.py +387 -0
  102. terraback/cli/azure/loadbalancer/__init__.py +14 -0
  103. terraback/cli/azure/loadbalancer/load_balancers.py +16 -0
  104. terraback/cli/azure/network/__init__.py +104 -0
  105. terraback/cli/azure/network/nsgs.py +214 -0
  106. terraback/cli/azure/network/subnets.py +210 -0
  107. terraback/cli/azure/network/vnets.py +198 -0
  108. terraback/cli/azure/session.py +87 -0
  109. terraback/cli/azure/storage/__init__.py +107 -0
  110. terraback/cli/azure/storage/storage_accounts.py +257 -0
  111. terraback/cli/commands/__init__.py +1 -0
  112. terraback/cli/commands/analyse.py +126 -0
  113. terraback/cli/commands/clean.py +49 -0
  114. terraback/cli/commands/list.py +54 -0
  115. terraback/cli/gcp/__init__.py +371 -0
  116. terraback/cli/gcp/compute/__init__.py +41 -0
  117. terraback/cli/gcp/compute/disks.py +187 -0
  118. terraback/cli/gcp/compute/images.py +57 -0
  119. terraback/cli/gcp/compute/instances.py +241 -0
  120. terraback/cli/gcp/compute/networks.py +138 -0
  121. terraback/cli/gcp/network/__init__.py +87 -0
  122. terraback/cli/gcp/network/firewalls.py +172 -0
  123. terraback/cli/gcp/network/networks.py +138 -0
  124. terraback/cli/gcp/network/subnets.py +193 -0
  125. terraback/cli/gcp/session.py +42 -0
  126. terraback/cli/gcp/storage/__init__.py +56 -0
  127. terraback/cli/gcp/storage/buckets.py +197 -0
  128. terraback/cli/main.py +346 -0
  129. terraback/core/__init__.py +0 -0
  130. terraback/core/license.py +337 -0
  131. terraback/templates/aws/caching/elasticache_memcached_cluster.tf.j2 +69 -0
  132. terraback/templates/aws/caching/elasticache_parameter_group.tf.j2 +27 -0
  133. terraback/templates/aws/caching/elasticache_redis_cluster.tf.j2 +69 -0
  134. terraback/templates/aws/caching/elasticache_replication_group.tf.j2 +136 -0
  135. terraback/templates/aws/caching/elasticache_subnet_group.tf.j2 +24 -0
  136. terraback/templates/aws/cdn/cloudfront_cache_policy.tf.j2 +77 -0
  137. terraback/templates/aws/cdn/cloudfront_distribution.tf.j2 +328 -0
  138. terraback/templates/aws/cdn/cloudfront_origin_access_control.tf.j2 +13 -0
  139. terraback/templates/aws/cdn/cloudfront_origin_request_policy.tf.j2 +55 -0
  140. terraback/templates/aws/compute/amis.tf.j2 +15 -0
  141. terraback/templates/aws/compute/autoscaling_group.tf.j2 +105 -0
  142. terraback/templates/aws/compute/autoscaling_policy.tf.j2 +78 -0
  143. terraback/templates/aws/compute/ec2.tf.j2 +54 -0
  144. terraback/templates/aws/compute/lambda_function.tf.j2 +42 -0
  145. terraback/templates/aws/compute/launch_configuration.tf.j2 +77 -0
  146. terraback/templates/aws/compute/launch_template.tf.j2 +80 -0
  147. terraback/templates/aws/container/ecr_repository.tf.j2 +44 -0
  148. terraback/templates/aws/container/ecs_cluster.tf.j2 +83 -0
  149. terraback/templates/aws/container/ecs_service.tf.j2 +157 -0
  150. terraback/templates/aws/database/rds_instance.tf.j2 +23 -0
  151. terraback/templates/aws/database/rds_parameter_group.tf.j2 +21 -0
  152. terraback/templates/aws/database/rds_subnet_group.tf.j2 +18 -0
  153. terraback/templates/aws/dns/route53_record.tf.j2 +31 -0
  154. terraback/templates/aws/dns/route53_zone.tf.j2 +6 -0
  155. terraback/templates/aws/integration/api_gateway_deployment.tf.j2 +21 -0
  156. terraback/templates/aws/integration/api_gateway_integration.tf.j2 +16 -0
  157. terraback/templates/aws/integration/api_gateway_method.tf.j2 +9 -0
  158. terraback/templates/aws/integration/api_gateway_resource.tf.j2 +9 -0
  159. terraback/templates/aws/integration/api_gateway_rest_api.tf.j2 +82 -0
  160. terraback/templates/aws/integration/api_gateway_stage.tf.j2 +9 -0
  161. terraback/templates/aws/integration/lambda_permission.tf.j2 +16 -0
  162. terraback/templates/aws/management/ssm_document.tf.j2 +39 -0
  163. terraback/templates/aws/management/ssm_maintenance_window.tf.j2 +112 -0
  164. terraback/templates/aws/management/ssm_parameter.tf.j2 +47 -0
  165. terraback/templates/aws/messaging/sns_subscription.tf.j2 +38 -0
  166. terraback/templates/aws/messaging/sns_topic.tf.j2 +47 -0
  167. terraback/templates/aws/messaging/sqs_queue.tf.j2 +53 -0
  168. terraback/templates/aws/monitoring/cloudwatch_alarm.tf.j2 +105 -0
  169. terraback/templates/aws/monitoring/cloudwatch_dashboard.tf.j2 +7 -0
  170. terraback/templates/aws/monitoring/cloudwatch_log_group.tf.j2 +19 -0
  171. terraback/templates/aws/networking/classic_load_balancer.tf.j2 +46 -0
  172. terraback/templates/aws/networking/eips.tf.j2 +19 -0
  173. terraback/templates/aws/networking/elbv2_listener.tf.j2 +164 -0
  174. terraback/templates/aws/networking/elbv2_listener_rule.tf.j2 +181 -0
  175. terraback/templates/aws/networking/elbv2_load_balancer.tf.j2 +114 -0
  176. terraback/templates/aws/networking/elbv2_ssl_policy.tf.j2 +36 -0
  177. terraback/templates/aws/networking/elbv2_target_group.tf.j2 +97 -0
  178. terraback/templates/aws/networking/elbv2_target_group_attachments.tf.j2 +22 -0
  179. terraback/templates/aws/networking/internet_gateway.tf.j2 +18 -0
  180. terraback/templates/aws/networking/nat_gateway.tf.j2 +26 -0
  181. terraback/templates/aws/networking/network_interfaces.tf.j2 +50 -0
  182. terraback/templates/aws/networking/route_table.tf.j2 +75 -0
  183. terraback/templates/aws/networking/security_groups.tf.j2 +44 -0
  184. terraback/templates/aws/networking/subnets.tf.j2 +21 -0
  185. terraback/templates/aws/networking/vpc.tf.j2 +14 -0
  186. terraback/templates/aws/networking/vpc_endpoint.tf.j2 +49 -0
  187. terraback/templates/aws/networking/wafv2_web_acl_association.tf.j2 +6 -0
  188. terraback/templates/aws/security/acm_certificate.tf.j2 +89 -0
  189. terraback/templates/aws/security/iam_policies.tf.j2 +11 -0
  190. terraback/templates/aws/security/iam_roles.tf.j2 +18 -0
  191. terraback/templates/aws/security/key_pairs.tf.j2 +16 -0
  192. terraback/templates/aws/security/secretsmanager_secret.tf.j2 +90 -0
  193. terraback/templates/aws/security/secretsmanager_secret_version.tf.j2 +23 -0
  194. terraback/templates/aws/security/ssm_document.tf.j2 +59 -0
  195. terraback/templates/aws/security/ssm_maintenance_window.tf.j2 +159 -0
  196. terraback/templates/aws/security/ssm_parameter.tf.j2 +58 -0
  197. terraback/templates/aws/serverless/lambda_layer_version.tf.j2 +22 -0
  198. terraback/templates/aws/storage/ebs_snapshot.tf.j2 +34 -0
  199. terraback/templates/aws/storage/ecs_task_definition.tf.j2 +343 -0
  200. terraback/templates/aws/storage/efs_access_point.tf.j2 +41 -0
  201. terraback/templates/aws/storage/efs_file_system.tf.j2 +57 -0
  202. terraback/templates/aws/storage/efs_mount_target.tf.j2 +22 -0
  203. terraback/templates/aws/storage/s3_bucket.tf.j2 +29 -0
  204. terraback/templates/aws/storage/volumes.tf.j2 +32 -0
  205. terraback/templates/azure/compute/azure_managed_disk.tf.j2 +105 -0
  206. terraback/templates/azure/compute/azure_virtual_machine.tf.j2 +139 -0
  207. terraback/templates/azure/compute/virtual_machine.tf.j2 +111 -0
  208. terraback/templates/azure/network/azure_network_security_group.tf.j2 +73 -0
  209. terraback/templates/azure/network/azure_subnet.tf.j2 +72 -0
  210. terraback/templates/azure/network/azure_virtual_network.tf.j2 +44 -0
  211. terraback/templates/azure/network/vnet_import.json.tf.j2 +0 -0
  212. terraback/templates/azure/networking/azure_network_security_group.tf.j2 +77 -0
  213. terraback/templates/azure/networking/azure_subnet.tf.j2 +76 -0
  214. terraback/templates/azure/storage/azure_storage_account.tf.j2 +120 -0
  215. terraback/templates/azure/storage/storage_account.tf.j2 +15 -0
  216. terraback/templates/azure/storage/storage_account_import.json.j2 +12 -0
  217. terraback/templates/gcp/compute/gcp_disk.tf.j2 +35 -0
  218. terraback/templates/gcp/gcp_instance.tf.j2 +65 -0
  219. terraback/templates/gcp/network/gcp_firewall.tf.j2 +68 -0
  220. terraback/templates/gcp/network/gcp_network.tf.j2 +23 -0
  221. terraback/templates/gcp/network/gcp_subnet.tf.j2 +46 -0
  222. terraback/templates/gcp/storage/gcp_bucket.tf.j2 +97 -0
  223. terraback/terraform_generator/__init__.py +1 -0
  224. terraback/terraform_generator/imports.py +57 -0
  225. terraback/terraform_generator/writer.py +192 -0
  226. terraback/tests/__init__.py +0 -0
  227. terraback/tests/integration/__init__.py +0 -0
  228. terraback/tests/integration/test_vpc_scanner.py +74 -0
  229. terraback/tests/unit/__init__.py +0 -0
  230. terraback/tests/unit/test_cross_scan_registry.py +102 -0
  231. terraback/utils/cleanup.py +15 -0
  232. terraback/utils/cross_scan_registry.py +448 -0
  233. terraback/utils/importer.py +75 -0
  234. terraback-0.0.0.dist-info/METADATA +446 -0
  235. terraback-0.0.0.dist-info/RECORD +239 -0
  236. terraback-0.0.0.dist-info/WHEEL +5 -0
  237. terraback-0.0.0.dist-info/entry_points.txt +2 -0
  238. terraback-0.0.0.dist-info/licenses/LICENSE +120 -0
  239. terraback-0.0.0.dist-info/top_level.txt +1 -0
terraback/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "0.0.0"
File without changes
@@ -0,0 +1,390 @@
1
+ # terraback/cli/main.py
2
+ import typer
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ # Clean provider imports
7
+ from terraback.cli import aws, azure, gcp
8
+
9
+ # Import command modules
10
+ from terraback.cli.commands.clean import app as clean_app
11
+ from terraback.cli.commands.list import app as list_app
12
+ from terraback.cli.commands.analyse import app as analyse_app
13
+
14
+ # Import licensing
15
+ from terraback.core.license import (
16
+ activate_license, get_active_license, get_active_tier, get_license_status,
17
+ require_professional, require_enterprise, check_feature_access, Tier
18
+ )
19
+
20
+ app = typer.Typer(
21
+ name="terraback",
22
+ help="Terraback: A tool to generate Terraform from existing cloud infrastructure.",
23
+ no_args_is_help=True
24
+ )
25
+
26
+ # License Command Group
27
+ license_app = typer.Typer(help="Manage your Terraback license.")
28
+
29
+ @license_app.command("status")
30
+ def license_status():
31
+ """Check the current license status and tier."""
32
+ status = get_license_status()
33
+
34
+ typer.echo(f"Active Feature Tier: {typer.style(status['active_tier'].capitalize(), bold=True)}")
35
+
36
+ if status['has_license']:
37
+ typer.secho("\nLicense Details:", fg=typer.colors.GREEN)
38
+ typer.echo(f" - Email: {status.get('email', 'N/A')}")
39
+ typer.echo(f" - Tier: {status.get('tier', 'N/A').capitalize()}")
40
+ typer.echo(f" - Expires: {status.get('expires', 'N/A')}")
41
+ if status.get('order_id'):
42
+ typer.echo(f" - Order ID: {status.get('order_id')}")
43
+ else:
44
+ typer.secho("\nNo active license key found.", fg=typer.colors.YELLOW)
45
+ typer.echo("Running in Community mode.")
46
+ typer.echo("\nCommunity Edition includes:")
47
+ typer.echo(" Unlimited core resources (EC2, VPC, S3, VMs, VNets, Storage)")
48
+ typer.echo(" Basic dependency mapping")
49
+ typer.echo(" Multi-cloud support (AWS, Azure, GCP)")
50
+ typer.echo(" Community support via GitHub")
51
+ typer.echo("\nTo unlock advanced services (RDS, Lambda, EKS, etc.):")
52
+ typer.echo(" Get Migration Pass: https://terraback.io/pricing")
53
+ typer.echo(" Activate license: terraback license activate <key>")
54
+
55
+ @license_app.command("activate")
56
+ def license_activate(key: str = typer.Argument(..., help="Your license key.")):
57
+ """Activate a new license key."""
58
+ if activate_license(key):
59
+ typer.secho("License activated successfully!", fg=typer.colors.GREEN, bold=True)
60
+ typer.echo()
61
+ license_status()
62
+ else:
63
+ typer.secho("License activation failed.", fg=typer.colors.RED, bold=True)
64
+ typer.echo("Please check that:")
65
+ typer.echo(" - The license key is copied correctly")
66
+ typer.echo(" - The license hasn't expired")
67
+ typer.echo(" - You have write permissions to ~/.terraback/")
68
+ typer.echo("\nIf you continue to have issues, contact support@terraback.io")
69
+ raise typer.Exit(code=1)
70
+
71
+ @license_app.command("validate")
72
+ def license_validate():
73
+ """Validate the current license and show detailed information."""
74
+ license_data = get_active_license()
75
+
76
+ if license_data:
77
+ typer.secho("License is valid and active", fg=typer.colors.GREEN, bold=True)
78
+ typer.echo(f"\nLicense Information:")
79
+ typer.echo(f" Email: {license_data.get('email', 'N/A')}")
80
+ typer.echo(f" Tier: {license_data.get('tier', 'N/A').capitalize()}")
81
+ typer.echo(f" Issued: {license_data.get('iat', 'N/A')}")
82
+ typer.echo(f" Expires: {license_data.get('expiry', 'N/A')}")
83
+
84
+ tier = license_data.get('tier', Tier.COMMUNITY)
85
+ if tier == Tier.PROFESSIONAL:
86
+ typer.echo(f"\nProfessional Features Unlocked:")
87
+ typer.echo(f" - Advanced AWS services (RDS, Lambda, EKS, etc.)")
88
+ typer.echo(f" - Dependency scanning with --with-deps")
89
+ typer.echo(f" - Multi-account support")
90
+ typer.echo(f" - Priority email support")
91
+ elif tier == Tier.ENTERPRISE:
92
+ typer.echo(f"\nEnterprise Features Unlocked:")
93
+ typer.echo(f" - All Professional features")
94
+ typer.echo(f" - Custom scanners and integrations")
95
+ typer.echo(f" - SSO integration")
96
+ typer.echo(f" - Dedicated support")
97
+ else:
98
+ typer.secho("No valid license found", fg=typer.colors.RED, bold=True)
99
+ typer.echo("\nRunning in Community mode with core features only.")
100
+ raise typer.Exit(code=1)
101
+
102
+ # Cache Command Group
103
+ cache_app = typer.Typer(help="Manage terraback cache")
104
+
105
+ @cache_app.command("stats")
106
+ def cache_stats():
107
+ """Show cache statistics."""
108
+ from terraback.utils.scan_cache import get_scan_cache
109
+
110
+ cache = get_scan_cache()
111
+ stats = cache.get_stats()
112
+
113
+ typer.echo("\nCache Statistics:")
114
+ typer.echo(f" Hit Rate: {stats['hit_rate']}")
115
+ typer.echo(f" Total Hits: {stats['hits']}")
116
+ typer.echo(f" Total Misses: {stats['misses']}")
117
+ typer.echo(f" Cache Size: {stats['total_size_kb']} KB")
118
+ typer.echo(f" Memory Cache Items: {stats['memory_cache_size']}")
119
+ typer.echo(f" TTL: {stats['ttl_minutes']:.0f} minutes")
120
+
121
+ @cache_app.command("clear")
122
+ def cache_clear(
123
+ confirm: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation")
124
+ ):
125
+ """Clear all cached data."""
126
+ from terraback.utils.scan_cache import get_scan_cache
127
+
128
+ if not confirm:
129
+ confirm = typer.confirm("Are you sure you want to clear all cached data?")
130
+
131
+ if confirm:
132
+ cache = get_scan_cache()
133
+ cache.clear()
134
+ typer.echo("Cache cleared successfully!")
135
+ else:
136
+ typer.echo("Cache clear cancelled.")
137
+
138
+ @cache_app.command("invalidate")
139
+ def cache_invalidate(
140
+ service: Optional[str] = typer.Option(None, help="Cloud service name (e.g., ec2, s3)"),
141
+ operation: Optional[str] = typer.Option(None, help="Operation name (e.g., describe_instances)")
142
+ ):
143
+ """Invalidate specific cache entries."""
144
+ from terraback.utils.scan_cache import get_scan_cache
145
+
146
+ cache = get_scan_cache()
147
+ count = cache.invalidate_pattern(service, operation)
148
+
149
+ if service and operation:
150
+ typer.echo(f"Invalidated {count} cache entries for {service}:{operation}")
151
+ elif service:
152
+ typer.echo(f"Invalidated {count} cache entries for service: {service}")
153
+ elif operation:
154
+ typer.echo(f"Invalidated {count} cache entries for operation: {operation}")
155
+ else:
156
+ typer.echo(f"Invalidated {count} cache entries")
157
+
158
+ # Add command groups to main app
159
+ app.add_typer(aws.app, name="aws", help="Amazon Web Services resources")
160
+ app.add_typer(azure.app, name="azure", help="Microsoft Azure resources")
161
+ app.add_typer(gcp.app, name="gcp", help="Google Cloud Platform resources")
162
+ app.add_typer(clean_app, name="clean", help="Clean generated files")
163
+ app.add_typer(list_app, name="list", help="List scanned resources")
164
+ app.add_typer(analyse_app, name="analyse", help="Analyse Terraform state")
165
+ app.add_typer(license_app, name="license", help="License management")
166
+ app.add_typer(cache_app, name="cache", help="Cache management")
167
+
168
+ @app.callback()
169
+ def main_callback():
170
+ """Initialize providers on first command."""
171
+ # Register providers with cross-scan registry
172
+ aws.register()
173
+ azure.register()
174
+ gcp.register()
175
+
176
+ @app.command("scan-all")
177
+ def scan_all(
178
+ provider: str = typer.Argument(..., help="Cloud provider: 'aws', 'azure', or 'gcp'"),
179
+ output_dir: Path = typer.Option("generated", "-o", "--output-dir", help="Directory to save Terraform files"),
180
+ profile: Optional[str] = typer.Option(None, "--profile", "-p", help="AWS profile name"),
181
+ region: Optional[str] = typer.Option(None, "--region", "-r", help="AWS region, Azure location, or GCP region"),
182
+ subscription_id: Optional[str] = typer.Option(None, "--subscription-id", "-s", help="Azure subscription ID"),
183
+ project_id: Optional[str] = typer.Option(None, "--project-id", help="GCP project ID"),
184
+ resource_group: Optional[str] = typer.Option(None, "--resource-group", "-g", help="Azure resource group"),
185
+ zone: Optional[str] = typer.Option(None, "--zone", "-z", help="GCP zone"),
186
+ with_deps: bool = typer.Option(False, "--with-deps", help="Recursively scan dependencies (Professional feature)")
187
+ ):
188
+ """Scan all resources for a specific cloud provider."""
189
+ provider = provider.lower()
190
+
191
+ if provider == "aws":
192
+ # Delegate to AWS scan-all
193
+ from terraback.cli.aws import scan_all_aws
194
+ scan_all_aws(
195
+ output_dir=output_dir,
196
+ profile=profile,
197
+ region=region,
198
+ with_deps=with_deps
199
+ )
200
+ elif provider == "azure":
201
+ # Delegate to Azure scan-all
202
+ from terraback.cli.azure import scan_all_azure
203
+ scan_all_azure(
204
+ output_dir=output_dir,
205
+ subscription_id=subscription_id,
206
+ location=region, # region is used as location for Azure
207
+ resource_group_name=resource_group,
208
+ with_deps=with_deps
209
+ )
210
+ elif provider == "gcp":
211
+ # Delegate to GCP scan-all
212
+ from terraback.cli.gcp import scan_all_gcp
213
+ scan_all_gcp(
214
+ output_dir=output_dir,
215
+ project_id=project_id,
216
+ region=region,
217
+ zone=zone,
218
+ with_deps=with_deps
219
+ )
220
+ else:
221
+ typer.echo(f"Error: Unknown provider '{provider}'. Use 'aws', 'azure', or 'gcp'.", err=True)
222
+ raise typer.Exit(code=1)
223
+
224
+ @app.command("scan-recursive")
225
+ @require_professional
226
+ def scan_recursive(
227
+ resource_type: str = typer.Argument(..., help="Initial resource type to scan"),
228
+ output_dir: Path = typer.Option("generated", "-o", "--output-dir"),
229
+ profile: Optional[str] = typer.Option(None, "--profile", "-p"),
230
+ region: Optional[str] = typer.Option(None, "--region", "-r"),
231
+ subscription_id: Optional[str] = typer.Option(None, "--subscription-id", "-s"),
232
+ project_id: Optional[str] = typer.Option(None, "--project-id"),
233
+ zone: Optional[str] = typer.Option(None, "--zone", "-z"),
234
+ use_cache: bool = typer.Option(True, "--cache/--no-cache")
235
+ ):
236
+ """(Professional Feature) Recursively scan cloud resources with smart dependency resolution."""
237
+ from datetime import timedelta
238
+ from terraback.utils.scan_cache import get_scan_cache
239
+ from terraback.utils.cross_scan_registry import recursive_scan as base_recursive_scan
240
+
241
+ # Normalize resource type
242
+ resource_type_map = {
243
+ # Azure aliases
244
+ 'vm': 'azure_virtual_machine',
245
+ 'vms': 'azure_virtual_machine',
246
+ 'disk': 'azure_managed_disk',
247
+ 'disks': 'azure_managed_disk',
248
+ 'vnet': 'azure_virtual_network',
249
+ 'vnets': 'azure_virtual_network',
250
+ 'subnet': 'azure_subnet',
251
+ 'subnets': 'azure_subnet',
252
+ 'nsg': 'azure_network_security_group',
253
+ 'nsgs': 'azure_network_security_group',
254
+ # AWS aliases
255
+ 'instance': 'ec2',
256
+ 'instances': 'ec2',
257
+ 'bucket': 's3_bucket',
258
+ 'buckets': 's3_bucket',
259
+ # GCP aliases
260
+ 'gcp_vm': 'gcp_instance',
261
+ 'gcp_vms': 'gcp_instance',
262
+ 'gcp_bucket': 'gcp_bucket',
263
+ 'gcp_buckets': 'gcp_bucket',
264
+ }
265
+
266
+ normalized_type = resource_type_map.get(resource_type.lower(), resource_type.lower())
267
+ typer.echo(f"Starting Professional recursive scan for '{normalized_type}'...")
268
+
269
+ is_azure = normalized_type.startswith('azure_')
270
+ is_gcp = normalized_type.startswith('gcp_')
271
+
272
+ kwargs = {
273
+ 'resource_type': normalized_type,
274
+ 'output_dir': output_dir
275
+ }
276
+
277
+ if is_azure:
278
+ from terraback.cli.azure.session import get_default_subscription_id
279
+ if not subscription_id:
280
+ subscription_id = get_default_subscription_id()
281
+ if not subscription_id:
282
+ typer.echo("Error: No Azure subscription found. Please run 'az login'", err=True)
283
+ raise typer.Exit(code=1)
284
+ kwargs['subscription_id'] = subscription_id
285
+ kwargs['location'] = region
286
+ elif is_gcp:
287
+ from terraback.cli.gcp.session import get_default_project_id
288
+ if not project_id:
289
+ project_id = get_default_project_id()
290
+ if not project_id:
291
+ typer.echo("Error: No GCP project found. Please run 'gcloud config set project'", err=True)
292
+ raise typer.Exit(code=1)
293
+ kwargs['project_id'] = project_id
294
+ kwargs['region'] = region
295
+ kwargs['zone'] = zone
296
+ else:
297
+ # AWS
298
+ from terraback.cli.common.defaults import get_aws_defaults
299
+ defaults = get_aws_defaults()
300
+ kwargs['profile'] = profile or defaults['profile']
301
+ kwargs['region'] = region or defaults['region']
302
+
303
+ if use_cache:
304
+ cache = get_scan_cache(
305
+ cache_dir=output_dir / ".terraback" / "cache",
306
+ ttl=timedelta(minutes=60)
307
+ )
308
+ typer.echo("Caching enabled (TTL: 60 minutes)")
309
+
310
+ base_recursive_scan(**kwargs)
311
+
312
+ if use_cache:
313
+ stats = cache.get_stats()
314
+ typer.echo(f"\nCache Statistics:")
315
+ typer.echo(f" Hit Rate: {stats['hit_rate']}")
316
+ typer.echo(f" Cache Size: {stats['total_size_kb']} KB")
317
+
318
+ @app.command("auth-check")
319
+ def check_auth():
320
+ """Check authentication status for all cloud providers."""
321
+ typer.echo("Checking cloud authentication status...\n")
322
+
323
+ # Check AWS
324
+ try:
325
+ from terraback.cli.aws.session import get_boto_session
326
+ session = get_boto_session()
327
+ sts = session.client('sts')
328
+ identity = sts.get_caller_identity()
329
+ typer.echo("AWS: Authenticated")
330
+ typer.echo(f" Account: {identity['Account']}")
331
+ typer.echo(f" User/Role: {identity['Arn'].split('/')[-1]}")
332
+ typer.echo(f" Region: {session.region_name}")
333
+ except Exception:
334
+ typer.echo("AWS: Not authenticated (run: aws configure)")
335
+
336
+ # Check Azure
337
+ try:
338
+ from terraback.cli.azure.session import get_default_subscription_id
339
+ sub_id = get_default_subscription_id()
340
+ if sub_id:
341
+ typer.echo("\nAzure: Authenticated")
342
+ typer.echo(f" Subscription: {sub_id}")
343
+ else:
344
+ typer.echo("\nAzure: Not authenticated (run: az login)")
345
+ except Exception:
346
+ typer.echo("\nAzure: Not authenticated (run: az login)")
347
+
348
+ # Check GCP
349
+ try:
350
+ from terraback.cli.gcp.session import get_default_project_id
351
+ project_id = get_default_project_id()
352
+ if project_id:
353
+ typer.echo("\nGCP: Authenticated")
354
+ typer.echo(f" Project: {project_id}")
355
+ else:
356
+ typer.echo("\nGCP: Not authenticated (run: gcloud auth application-default login)")
357
+ except Exception:
358
+ typer.echo("\nGCP: Not authenticated (run: gcloud auth application-default login)")
359
+
360
+ @app.command("upgrade")
361
+ def upgrade_info():
362
+ """Show information about upgrading to Professional features."""
363
+ current_tier = get_active_tier()
364
+
365
+ if current_tier == Tier.COMMUNITY:
366
+ typer.echo("Upgrade to Professional for Advanced Features\n")
367
+
368
+ typer.echo("Your Current Plan: Community Edition (Free)")
369
+ typer.echo(" - Unlimited core resources (EC2, VPC, S3, VMs, VNets, Storage)")
370
+ typer.echo(" - Multi-cloud support (AWS, Azure, GCP)")
371
+ typer.echo(" - Basic dependency mapping\n")
372
+
373
+ typer.echo("Unlock with Migration Pass ($299 for 3 months):")
374
+ typer.echo(" - Advanced AWS services (RDS, Lambda, EKS, ALB, Route53, etc.)")
375
+ typer.echo(" - Recursive dependency scanning (--with-deps)")
376
+ typer.echo(" - Multi-account/subscription support")
377
+ typer.echo(" - Priority email support")
378
+ typer.echo(" - Advanced caching and performance features\n")
379
+
380
+ typer.echo("Get Migration Pass: https://terraback.io/pricing")
381
+ typer.echo("Enterprise needs: sales@terraback.io")
382
+ elif current_tier == Tier.PROFESSIONAL:
383
+ typer.secho("You have Professional access!", fg=typer.colors.GREEN, bold=True)
384
+ typer.echo("All advanced features are unlocked.")
385
+ elif current_tier == Tier.ENTERPRISE:
386
+ typer.secho("You have Enterprise access!", fg=typer.colors.GREEN, bold=True)
387
+ typer.echo("All features including enterprise support are available.")
388
+
389
+ if __name__ == "__main__":
390
+ app()
@@ -0,0 +1,53 @@
1
+ from terraback.core.license import require_professional
2
+ import typer
3
+ from pathlib import Path
4
+
5
+ from .certificates import scan_certificates, list_certificates, import_certificate
6
+
7
+ from terraback.utils.cross_scan_registry import register_scan_function, cross_scan_registry
8
+
9
+ app = typer.Typer(
10
+ name="acm",
11
+ help="Manage AWS Certificate Manager (ACM) resources like SSL/TLS certificates.",
12
+ no_args_is_help=True
13
+ )
14
+
15
+ # --- Certificate Commands ---
16
+ @app.command(name="scan-certificates", help="Scan ACM SSL/TLS certificates.")
17
+ @require_professional
18
+ def scan_certificates_command(
19
+ output_dir: Path = typer.Option("generated", help="Directory to save Terraform files"),
20
+ profile: str = typer.Option(None, help="AWS CLI profile to use"),
21
+ region: str = typer.Option("us-east-1", help="AWS region"),
22
+ include_imported: bool = typer.Option(True, help="Include imported certificates"),
23
+ include_issued: bool = typer.Option(True, help="Include ACM-issued certificates")
24
+ ):
25
+ scan_certificates(output_dir, profile, region, include_imported, include_issued)
26
+
27
+ @app.command(name="list-certificates", help="List scanned ACM certificates.")
28
+ @require_professional
29
+ def list_certificates_command(output_dir: Path = typer.Option("generated")):
30
+ list_certificates(output_dir)
31
+
32
+ @app.command(name="import-certificate", help="Import an ACM certificate by ARN.")
33
+ @require_professional
34
+ def import_certificate_command(
35
+ certificate_arn: str,
36
+ output_dir: Path = typer.Option("generated")
37
+ ):
38
+ import_certificate(certificate_arn, output_dir)
39
+
40
+ # --- Registration ---
41
+ def register():
42
+ """Registers scan functions and dependencies for the ACM module."""
43
+ register_scan_function("acm_certificate", scan_certificates)
44
+
45
+ # ACM certificates are dependencies for other services
46
+ # Load balancers use ACM certificates for HTTPS listeners
47
+ cross_scan_registry.register_dependency("elbv2_listener", "acm_certificate")
48
+ # Classic load balancers can also use ACM certificates
49
+ cross_scan_registry.register_dependency("classic_load_balancer", "acm_certificate")
50
+ # API Gateway can use ACM certificates for custom domains
51
+ cross_scan_registry.register_dependency("api_gateway_rest_api", "acm_certificate")
52
+ # CloudFront distributions use ACM certificates (when we add CloudFront)
53
+ cross_scan_registry.register_dependency("cloudfront_distribution", "acm_certificate")
@@ -0,0 +1,117 @@
1
+ from pathlib import Path
2
+ from terraback.cli.aws.session import get_boto_session
3
+ from terraback.terraform_generator.writer import generate_tf
4
+ from terraback.terraform_generator.imports import generate_imports_file
5
+ from terraback.utils.importer import ImportManager
6
+
7
+ def scan_certificates(
8
+ output_dir: Path,
9
+ profile: str = None,
10
+ region: str = "us-east-1",
11
+ include_imported: bool = True,
12
+ include_issued: bool = True
13
+ ):
14
+ """
15
+ Scans for ACM certificates and generates Terraform code.
16
+ """
17
+ boto_session = get_boto_session(profile, region)
18
+ acm_client = boto_session.client("acm")
19
+
20
+ print(f"Scanning for ACM certificates in region {region}...")
21
+
22
+ # Build certificate status filters based on options
23
+ certificate_statuses = []
24
+ if include_issued:
25
+ certificate_statuses.extend(['ISSUED'])
26
+ if include_imported:
27
+ certificate_statuses.extend(['ISSUED']) # Imported certs also show as ISSUED
28
+
29
+ if not certificate_statuses:
30
+ print("No certificate types selected for scanning")
31
+ return
32
+
33
+ # Get all certificates using pagination
34
+ paginator = acm_client.get_paginator('list_certificates')
35
+ certificates = []
36
+
37
+ for page in paginator.paginate(CertificateStatuses=certificate_statuses):
38
+ for cert_summary in page['CertificateSummaryList']:
39
+ cert_arn = cert_summary['CertificateArn']
40
+
41
+ try:
42
+ # Get detailed certificate information
43
+ cert_detail = acm_client.describe_certificate(CertificateArn=cert_arn)
44
+ certificate = cert_detail['Certificate']
45
+
46
+ # Add computed fields for easier template usage
47
+ certificate['arn_sanitized'] = cert_arn.split('/')[-1].replace('-', '_').lower()
48
+ certificate['domain_sanitized'] = certificate['DomainName'].replace('.', '_').replace('*', 'wildcard').replace('-', '_').lower()
49
+
50
+ # Determine certificate type (ACM-issued vs imported)
51
+ if certificate.get('Type') == 'IMPORTED':
52
+ certificate['is_imported'] = True
53
+ certificate['is_acm_issued'] = False
54
+ else:
55
+ certificate['is_imported'] = False
56
+ certificate['is_acm_issued'] = True
57
+
58
+ # Format subject alternative names for easier template usage
59
+ if certificate.get('SubjectAlternativeNames'):
60
+ certificate['sans_formatted'] = certificate['SubjectAlternativeNames']
61
+ else:
62
+ certificate['sans_formatted'] = []
63
+
64
+ # Format domain validation options
65
+ if certificate.get('DomainValidationOptions'):
66
+ certificate['domain_validation_formatted'] = []
67
+ for dvo in certificate['DomainValidationOptions']:
68
+ formatted_dvo = {
69
+ 'DomainName': dvo['DomainName'],
70
+ 'ValidationDomain': dvo.get('ValidationDomain'),
71
+ 'ValidationStatus': dvo.get('ValidationStatus'),
72
+ 'ValidationMethod': dvo.get('ValidationMethod')
73
+ }
74
+ # Add DNS validation records if present
75
+ if dvo.get('ResourceRecord'):
76
+ formatted_dvo['ResourceRecord'] = dvo['ResourceRecord']
77
+ certificate['domain_validation_formatted'].append(formatted_dvo)
78
+ else:
79
+ certificate['domain_validation_formatted'] = []
80
+
81
+ # Get certificate tags
82
+ try:
83
+ tags_response = acm_client.list_tags_for_certificate(CertificateArn=cert_arn)
84
+ certificate['Tags'] = tags_response.get('Tags', [])
85
+ except Exception as e:
86
+ print(f" - Warning: Could not retrieve tags for certificate {cert_arn}: {e}")
87
+ certificate['Tags'] = []
88
+
89
+ certificates.append(certificate)
90
+
91
+ except Exception as e:
92
+ print(f" - Warning: Could not retrieve details for certificate {cert_arn}: {e}")
93
+ continue
94
+
95
+ # Filter certificates based on type if needed
96
+ if not include_imported:
97
+ certificates = [cert for cert in certificates if not cert['is_imported']]
98
+ if not include_issued:
99
+ certificates = [cert for cert in certificates if not cert['is_acm_issued']]
100
+
101
+ output_file = output_dir / "acm_certificate.tf"
102
+ generate_tf(certificates, "acm_certificate", output_file)
103
+ print(f"Generated Terraform for {len(certificates)} ACM certificates -> {output_file}")
104
+ generate_imports_file(
105
+ "acm_certificate",
106
+ certificates,
107
+ remote_resource_id_key="CertificateArn",
108
+ output_dir=output_dir
109
+ )
110
+
111
+ def list_certificates(output_dir: Path):
112
+ """Lists all ACM certificate resources previously generated."""
113
+ ImportManager(output_dir, "acm_certificate").list_all()
114
+
115
+ def import_certificate(certificate_arn: str, output_dir: Path):
116
+ """Runs terraform import for a specific ACM certificate by its ARN."""
117
+ ImportManager(output_dir, "acm_certificate").find_and_import(certificate_arn)
@@ -0,0 +1,27 @@
1
+ from terraback.core.license import require_professional
2
+ import typer
3
+ from pathlib import Path
4
+ from .rest_apis import scan_rest_apis
5
+
6
+ from terraback.utils.cross_scan_registry import register_scan_function, cross_scan_registry
7
+
8
+ app = typer.Typer(
9
+ name="apigateway",
10
+ help="Manage API Gateway REST API resources.",
11
+ no_args_is_help=True
12
+ )
13
+
14
+ @app.command(name="scan-rest-apis", help="Scan REST APIs and all their sub-resources.")
15
+ @require_professional
16
+ def scan_apis_command(output_dir: Path = typer.Option("generated"), profile: str = typer.Option(None), region: str = typer.Option("us-east-1")):
17
+ scan_rest_apis(output_dir, profile, region)
18
+
19
+ # Note: list and import commands are omitted for now due to the complexity of nested resources.
20
+
21
+ def register():
22
+ """Registers scan functions and dependencies for the API Gateway module."""
23
+ register_scan_function("api_gateway_rest_api", scan_rest_apis)
24
+
25
+ # Define dependencies
26
+ cross_scan_registry.register_dependency("api_gateway_integration", "lambda_function")
27
+ cross_scan_registry.register_dependency("lambda_function", "api_gateway_rest_api")