cloudwire 0.2.5__tar.gz → 0.2.11__tar.gz

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 (57) hide show
  1. {cloudwire-0.2.5 → cloudwire-0.2.11}/PKG-INFO +18 -20
  2. {cloudwire-0.2.5 → cloudwire-0.2.11}/README.md +11 -16
  3. cloudwire-0.2.11/cloudwire/__init__.py +8 -0
  4. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/main.py +42 -1
  5. cloudwire-0.2.11/cloudwire/static/assets/index-CJlbfCBD.js +40 -0
  6. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/static/index.html +1 -1
  7. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire.egg-info/PKG-INFO +18 -20
  8. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire.egg-info/SOURCES.txt +2 -2
  9. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire.egg-info/requires.txt +2 -0
  10. {cloudwire-0.2.5 → cloudwire-0.2.11}/pyproject.toml +17 -4
  11. cloudwire-0.2.5/cloudwire/__init__.py +0 -3
  12. cloudwire-0.2.5/cloudwire/static/assets/index-B17mpnyB.js +0 -40
  13. {cloudwire-0.2.5 → cloudwire-0.2.11}/LICENSE +0 -0
  14. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/__init__.py +0 -0
  15. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/aws_clients.py +0 -0
  16. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/errors.py +0 -0
  17. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/graph_store.py +0 -0
  18. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/hcl_parser.py +0 -0
  19. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/models.py +0 -0
  20. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/routes/__init__.py +0 -0
  21. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/routes/scan.py +0 -0
  22. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/routes/tags.py +0 -0
  23. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/routes/terraform.py +0 -0
  24. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scan_jobs.py +0 -0
  25. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanner.py +0 -0
  26. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/__init__.py +0 -0
  27. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/_utils.py +0 -0
  28. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/apigateway.py +0 -0
  29. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/appsync.py +0 -0
  30. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/cloudfront.py +0 -0
  31. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/cognito.py +0 -0
  32. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/dynamodb.py +0 -0
  33. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/ec2.py +0 -0
  34. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/ecs.py +0 -0
  35. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/elasticache.py +0 -0
  36. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/eventbridge.py +0 -0
  37. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/glue.py +0 -0
  38. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/iam.py +0 -0
  39. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/kinesis.py +0 -0
  40. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/lambda_.py +0 -0
  41. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/rds.py +0 -0
  42. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/redshift.py +0 -0
  43. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/route53.py +0 -0
  44. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/s3.py +0 -0
  45. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/sns.py +0 -0
  46. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/sqs.py +0 -0
  47. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/stepfunctions.py +0 -0
  48. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/scanners/vpc.py +0 -0
  49. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/services.py +0 -0
  50. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/app/terraform_parser.py +0 -0
  51. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/cli.py +0 -0
  52. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/static/assets/index-BlarXbuP.css +0 -0
  53. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire/static/favicon.svg +0 -0
  54. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire.egg-info/dependency_links.txt +0 -0
  55. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire.egg-info/entry_points.txt +0 -0
  56. {cloudwire-0.2.5 → cloudwire-0.2.11}/cloudwire.egg-info/top_level.txt +0 -0
  57. {cloudwire-0.2.5 → cloudwire-0.2.11}/setup.cfg +0 -0
@@ -1,10 +1,12 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.2
2
2
  Name: cloudwire
3
- Version: 0.2.5
3
+ Version: 0.2.11
4
4
  Summary: Scan and visualize your AWS infrastructure as an interactive graph
5
- License-Expression: MIT
5
+ License: MIT
6
6
  Project-URL: Homepage, https://github.com/Himanshu-370/cloudwire
7
7
  Project-URL: Issues, https://github.com/Himanshu-370/cloudwire/issues
8
+ Project-URL: Changelog, https://github.com/Himanshu-370/cloudwire/blob/main/CHANGELOG.md
9
+ Project-URL: Documentation, https://github.com/Himanshu-370/cloudwire/blob/main/docs/USAGE.md
8
10
  Keywords: aws,cloud,visualization,graph,infrastructure
9
11
  Classifier: Development Status :: 4 - Beta
10
12
  Classifier: Environment :: Console
@@ -25,6 +27,8 @@ License-File: LICENSE
25
27
  Provides-Extra: dev
26
28
  Requires-Dist: twine; extra == "dev"
27
29
  Requires-Dist: build; extra == "dev"
30
+ Requires-Dist: ruff>=0.4; extra == "dev"
31
+ Requires-Dist: mypy>=1.0; extra == "dev"
28
32
  Provides-Extra: dependencies
29
33
  Requires-Dist: fastapi>=0.100; extra == "dependencies"
30
34
  Requires-Dist: uvicorn>=0.20; extra == "dependencies"
@@ -35,7 +39,6 @@ Requires-Dist: pydantic>=2.0; extra == "dependencies"
35
39
  Requires-Dist: click>=8.0; extra == "dependencies"
36
40
  Requires-Dist: python-multipart>=0.0.5; extra == "dependencies"
37
41
  Requires-Dist: python-hcl2>=4.3; extra == "dependencies"
38
- Dynamic: license-file
39
42
 
40
43
  # CloudWire
41
44
 
@@ -54,16 +57,6 @@ No data leaves your system. AWS credentials never leave your terminal. The graph
54
57
  <img src="docs/cloudgraph.svg" alt="CloudWire — AWS infrastructure graph visualization" width="100%">
55
58
  </p>
56
59
 
57
- > **Note:** The screenshot above contains placeholder resource IDs. Replace `docs/cloudgraph.svg` with a sanitized screenshot from your own environment.
58
-
59
- <!-- TODO: Once a demo video is recorded, replace the static image above with:
60
- <p align="center">
61
- <a href="https://www.youtube.com/watch?v=YOUR_VIDEO_ID">
62
- <img src="docs/demo-thumbnail.png" alt="CloudWire demo — click to watch" width="100%">
63
- </a>
64
- </p>
65
- -->
66
-
67
60
  ---
68
61
 
69
62
  ## Quick start
@@ -87,6 +80,16 @@ On first load, select the services you want to scan from the top bar and click *
87
80
 
88
81
  ---
89
82
 
83
+ ## Why CloudWire?
84
+
85
+ Tools like [Rover](https://github.com/im2nguyen/rover), [Terravision](https://github.com/patrickchugh/terravision), and [Inframap](https://github.com/cycloidio/inframap) visualize infrastructure from Terraform state files. CloudWire takes a different approach:
86
+
87
+ - **Live scanning, not plan-file parsing** — CloudWire queries your AWS account directly via boto3, discovering resources and relationships in real time. No Terraform required. You can also import `.tfstate`/`.tf` files if you prefer.
88
+ - **Relationship inference** — edges aren't just "resource A references resource B." CloudWire resolves IAM policies, environment variable references, event triggers, and VPC containment to surface connections that don't appear in any state file.
89
+ - **Runs entirely local** — single Python process, no database, no cloud backend, no signup. Your AWS credentials never leave your machine.
90
+
91
+ ---
92
+
90
93
  ## Key features
91
94
 
92
95
  - **Interactive graph** — dark-themed canvas with animated data flow, pan/zoom, and SVG export
@@ -96,14 +99,9 @@ On first load, select the services you want to scan from the top bar and click *
96
99
  - **Tag-based scanning** — discover and scan resources by AWS tags
97
100
  - **Terraform import** — upload `.tfstate` or `.tf` files to visualize without AWS credentials
98
101
  - **Analysis tools** — blast radius, shortest path, architecture summary, pattern detection
99
- - **Four layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
102
+ - **Three layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
100
103
  - **Permission-aware** — missing IAM policies surfaced clearly, never blocks the scan
101
104
 
102
- <!-- TODO: Add 2-3 annotated screenshots here showing:
103
- 1. Full UI with sidebar + multi-service graph (Lambda → SQS → DynamoDB)
104
- 2. Inspector panel open on a node showing attributes and edges
105
- 3. VPC topology view with AZ grouping
106
- -->
107
105
 
108
106
  ---
109
107
 
@@ -15,16 +15,6 @@ No data leaves your system. AWS credentials never leave your terminal. The graph
15
15
  <img src="docs/cloudgraph.svg" alt="CloudWire — AWS infrastructure graph visualization" width="100%">
16
16
  </p>
17
17
 
18
- > **Note:** The screenshot above contains placeholder resource IDs. Replace `docs/cloudgraph.svg` with a sanitized screenshot from your own environment.
19
-
20
- <!-- TODO: Once a demo video is recorded, replace the static image above with:
21
- <p align="center">
22
- <a href="https://www.youtube.com/watch?v=YOUR_VIDEO_ID">
23
- <img src="docs/demo-thumbnail.png" alt="CloudWire demo — click to watch" width="100%">
24
- </a>
25
- </p>
26
- -->
27
-
28
18
  ---
29
19
 
30
20
  ## Quick start
@@ -48,6 +38,16 @@ On first load, select the services you want to scan from the top bar and click *
48
38
 
49
39
  ---
50
40
 
41
+ ## Why CloudWire?
42
+
43
+ Tools like [Rover](https://github.com/im2nguyen/rover), [Terravision](https://github.com/patrickchugh/terravision), and [Inframap](https://github.com/cycloidio/inframap) visualize infrastructure from Terraform state files. CloudWire takes a different approach:
44
+
45
+ - **Live scanning, not plan-file parsing** — CloudWire queries your AWS account directly via boto3, discovering resources and relationships in real time. No Terraform required. You can also import `.tfstate`/`.tf` files if you prefer.
46
+ - **Relationship inference** — edges aren't just "resource A references resource B." CloudWire resolves IAM policies, environment variable references, event triggers, and VPC containment to surface connections that don't appear in any state file.
47
+ - **Runs entirely local** — single Python process, no database, no cloud backend, no signup. Your AWS credentials never leave your machine.
48
+
49
+ ---
50
+
51
51
  ## Key features
52
52
 
53
53
  - **Interactive graph** — dark-themed canvas with animated data flow, pan/zoom, and SVG export
@@ -57,14 +57,9 @@ On first load, select the services you want to scan from the top bar and click *
57
57
  - **Tag-based scanning** — discover and scan resources by AWS tags
58
58
  - **Terraform import** — upload `.tfstate` or `.tf` files to visualize without AWS credentials
59
59
  - **Analysis tools** — blast radius, shortest path, architecture summary, pattern detection
60
- - **Four layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
60
+ - **Three layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
61
61
  - **Permission-aware** — missing IAM policies surfaced clearly, never blocks the scan
62
62
 
63
- <!-- TODO: Add 2-3 annotated screenshots here showing:
64
- 1. Full UI with sidebar + multi-service graph (Lambda → SQS → DynamoDB)
65
- 2. Inspector panel open on a node showing attributes and edges
66
- 3. VPC topology view with AZ grouping
67
- -->
68
63
 
69
64
  ---
70
65
 
@@ -0,0 +1,8 @@
1
+ """CloudWire — scan and visualize your AWS infrastructure."""
2
+
3
+ from importlib.metadata import version, PackageNotFoundError
4
+
5
+ try:
6
+ __version__ = version("cloudwire")
7
+ except PackageNotFoundError:
8
+ __version__ = "0.2.11" # fallback when running from source without pip install
@@ -43,9 +43,41 @@ app = FastAPI(title="CloudWire API", version=_app_version, lifespan=lifespan)
43
43
 
44
44
 
45
45
  # ---------------------------------------------------------------------------
46
- # Security headers middleware
46
+ # Middleware registered last-in first-out (outermost executes first)
47
47
  # ---------------------------------------------------------------------------
48
48
 
49
+ _MAX_JSON_BODY_BYTES = 2 * 1024 * 1024 # 2 MB
50
+
51
+
52
+ class RequestBodyLimitMiddleware(BaseHTTPMiddleware):
53
+ """Reject oversized JSON request bodies before Pydantic validation."""
54
+
55
+ async def dispatch(self, request: Request, call_next):
56
+ content_type = request.headers.get("content-type", "")
57
+ if "application/json" in content_type:
58
+ # Fast path: reject immediately if Content-Length header exceeds limit
59
+ content_length = request.headers.get("content-length")
60
+ if content_length and int(content_length) > _MAX_JSON_BODY_BYTES:
61
+ return JSONResponse(
62
+ status_code=413,
63
+ content=error_payload(
64
+ "payload_too_large",
65
+ f"Request body exceeds the {_MAX_JSON_BODY_BYTES // (1024 * 1024)} MB limit.",
66
+ ),
67
+ )
68
+ # Also check actual body size (handles chunked transfers / missing header)
69
+ body = await request.body()
70
+ if len(body) > _MAX_JSON_BODY_BYTES:
71
+ return JSONResponse(
72
+ status_code=413,
73
+ content=error_payload(
74
+ "payload_too_large",
75
+ f"Request body exceeds the {_MAX_JSON_BODY_BYTES // (1024 * 1024)} MB limit.",
76
+ ),
77
+ )
78
+ return await call_next(request)
79
+
80
+
49
81
  class SecurityHeadersMiddleware(BaseHTTPMiddleware):
50
82
  async def dispatch(self, request: Request, call_next):
51
83
  response = await call_next(request)
@@ -56,6 +88,7 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
56
88
  return response
57
89
 
58
90
 
91
+ app.add_middleware(RequestBodyLimitMiddleware)
59
92
  app.add_middleware(SecurityHeadersMiddleware)
60
93
 
61
94
 
@@ -123,6 +156,14 @@ if _STATIC_DIR.is_dir() and ((_STATIC_DIR / "assets").is_dir()):
123
156
  app.mount("/assets", StaticFiles(directory=str(_STATIC_DIR / "assets")), name="assets")
124
157
 
125
158
 
159
+ @app.api_route("/api/{api_path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], include_in_schema=False)
160
+ def api_not_found(api_path: str) -> JSONResponse:
161
+ return JSONResponse(
162
+ status_code=404,
163
+ content=error_payload("not_found", f"API endpoint '/api/{api_path}' not found."),
164
+ )
165
+
166
+
126
167
  @app.get("/{full_path:path}", include_in_schema=False)
127
168
  def spa_fallback(full_path: str) -> FileResponse:
128
169
  index = _STATIC_DIR / "index.html"