cloudwire 0.2.5__tar.gz → 0.2.6__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.6}/PKG-INFO +6 -17
  2. {cloudwire-0.2.5 → cloudwire-0.2.6}/README.md +1 -16
  3. cloudwire-0.2.6/cloudwire/__init__.py +8 -0
  4. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/main.py +42 -1
  5. cloudwire-0.2.6/cloudwire/static/assets/index-CJlbfCBD.js +40 -0
  6. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/static/index.html +1 -1
  7. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire.egg-info/PKG-INFO +6 -17
  8. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire.egg-info/SOURCES.txt +2 -2
  9. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire.egg-info/requires.txt +2 -0
  10. {cloudwire-0.2.5 → cloudwire-0.2.6}/pyproject.toml +15 -2
  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.6}/LICENSE +0 -0
  14. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/__init__.py +0 -0
  15. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/aws_clients.py +0 -0
  16. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/errors.py +0 -0
  17. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/graph_store.py +0 -0
  18. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/hcl_parser.py +0 -0
  19. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/models.py +0 -0
  20. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/routes/__init__.py +0 -0
  21. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/routes/scan.py +0 -0
  22. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/routes/tags.py +0 -0
  23. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/routes/terraform.py +0 -0
  24. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scan_jobs.py +0 -0
  25. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanner.py +0 -0
  26. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/__init__.py +0 -0
  27. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/_utils.py +0 -0
  28. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/apigateway.py +0 -0
  29. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/appsync.py +0 -0
  30. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/cloudfront.py +0 -0
  31. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/cognito.py +0 -0
  32. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/dynamodb.py +0 -0
  33. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/ec2.py +0 -0
  34. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/ecs.py +0 -0
  35. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/elasticache.py +0 -0
  36. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/eventbridge.py +0 -0
  37. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/glue.py +0 -0
  38. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/iam.py +0 -0
  39. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/kinesis.py +0 -0
  40. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/lambda_.py +0 -0
  41. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/rds.py +0 -0
  42. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/redshift.py +0 -0
  43. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/route53.py +0 -0
  44. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/s3.py +0 -0
  45. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/sns.py +0 -0
  46. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/sqs.py +0 -0
  47. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/stepfunctions.py +0 -0
  48. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/scanners/vpc.py +0 -0
  49. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/services.py +0 -0
  50. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/app/terraform_parser.py +0 -0
  51. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/cli.py +0 -0
  52. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/static/assets/index-BlarXbuP.css +0 -0
  53. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire/static/favicon.svg +0 -0
  54. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire.egg-info/dependency_links.txt +0 -0
  55. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire.egg-info/entry_points.txt +0 -0
  56. {cloudwire-0.2.5 → cloudwire-0.2.6}/cloudwire.egg-info/top_level.txt +0 -0
  57. {cloudwire-0.2.5 → cloudwire-0.2.6}/setup.cfg +0 -0
@@ -1,10 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudwire
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Scan and visualize your AWS infrastructure as an interactive graph
5
5
  License-Expression: 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"
@@ -54,16 +58,6 @@ No data leaves your system. AWS credentials never leave your terminal. The graph
54
58
  <img src="docs/cloudgraph.svg" alt="CloudWire — AWS infrastructure graph visualization" width="100%">
55
59
  </p>
56
60
 
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
61
  ---
68
62
 
69
63
  ## Quick start
@@ -96,14 +90,9 @@ On first load, select the services you want to scan from the top bar and click *
96
90
  - **Tag-based scanning** — discover and scan resources by AWS tags
97
91
  - **Terraform import** — upload `.tfstate` or `.tf` files to visualize without AWS credentials
98
92
  - **Analysis tools** — blast radius, shortest path, architecture summary, pattern detection
99
- - **Four layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
93
+ - **Three layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
100
94
  - **Permission-aware** — missing IAM policies surfaced clearly, never blocks the scan
101
95
 
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
96
 
108
97
  ---
109
98
 
@@ -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
@@ -57,14 +47,9 @@ On first load, select the services you want to scan from the top bar and click *
57
47
  - **Tag-based scanning** — discover and scan resources by AWS tags
58
48
  - **Terraform import** — upload `.tfstate` or `.tf` files to visualize without AWS credentials
59
49
  - **Analysis tools** — blast radius, shortest path, architecture summary, pattern detection
60
- - **Four layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
50
+ - **Three layout modes** — Circular, Flow, Swimlane — switchable from the toolbar
61
51
  - **Permission-aware** — missing IAM policies surfaced clearly, never blocks the scan
62
52
 
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
53
 
69
54
  ---
70
55
 
@@ -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.6" # 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"