nuvu-scan 1.3.7__tar.gz → 1.3.8__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.
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/PKG-INFO +30 -8
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/README.md +26 -4
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/RELEASE.md +2 -2
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/commands/scan.py +62 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/aws_scanner.py +14 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/pyproject.toml +4 -4
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/.github/workflows/ci.yml +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/.github/workflows/release.yml +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/.gitignore +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/CONTRIBUTING.md +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/DEVELOPMENT_STATUS.md +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/commands/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/formatters/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/formatters/csv.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/formatters/html.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/formatters/json.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/cli/main.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/analyzers/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/base.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/models/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/athena.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/cost_explorer.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/glue.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/iam.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/mwaa.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/redshift.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/s3.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/bigquery.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/billing.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/dataproc.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/gcs.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/gemini.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/iam.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/collectors/pubsub.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/gcp/gcp_scanner.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/tests/__init__.py +0 -0
- {nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/tests/test_base.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nuvu-scan
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.8
|
|
4
4
|
Summary: Multi-Cloud Data Asset Control - CLI tool for discovering and analyzing cloud data infrastructure
|
|
5
5
|
Project-URL: Homepage, https://nuvu.dev
|
|
6
|
-
Project-URL: Documentation, https://github.com/
|
|
7
|
-
Project-URL: Repository, https://github.com/
|
|
8
|
-
Project-URL: Issues, https://github.com/
|
|
6
|
+
Project-URL: Documentation, https://github.com/nuvudev/nuvu-scan#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/nuvudev/nuvu-scan
|
|
8
|
+
Project-URL: Issues, https://github.com/nuvudev/nuvu-scan/issues
|
|
9
9
|
Author-email: Nuvu <info@nuvu.dev>
|
|
10
10
|
License: Apache-2.0
|
|
11
11
|
Keywords: aws,cloud,data,governance,infrastructure,scanning
|
|
@@ -69,6 +69,28 @@ pip install nuvu-scan
|
|
|
69
69
|
|
|
70
70
|
## Usage
|
|
71
71
|
|
|
72
|
+
### Optional: Push results to Nuvu Cloud
|
|
73
|
+
|
|
74
|
+
Nuvu Scan is fully open-source and runs standalone — no account required.
|
|
75
|
+
If you want dashboards, team workflows, and long‑term history, you can optionally push results to Nuvu Cloud.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Push results to Nuvu Cloud (optional)
|
|
79
|
+
nuvu scan --provider aws --push --api-key your_nuvu_api_key
|
|
80
|
+
|
|
81
|
+
# Or use environment variable
|
|
82
|
+
export NUVU_API_KEY=your_nuvu_api_key
|
|
83
|
+
nuvu scan --provider aws --push
|
|
84
|
+
|
|
85
|
+
# Custom cloud URL (defaults to https://nuvu.dev)
|
|
86
|
+
nuvu scan --provider aws --push --nuvu-cloud-url https://nuvu.dev
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
What this means for open‑source users:
|
|
90
|
+
- You can keep everything local and export JSON/CSV/HTML.
|
|
91
|
+
- No cloud credentials are ever sent to Nuvu Cloud — only scan results.
|
|
92
|
+
- The data collected is identical whether you run locally or push.
|
|
93
|
+
|
|
72
94
|
### AWS Scanning
|
|
73
95
|
|
|
74
96
|
**Prerequisites:** Create an IAM user or role with the read-only policy from `aws-iam-policy.json`. See the [AWS Setup](#aws-v1---available-now) section below for detailed instructions.
|
|
@@ -342,7 +364,7 @@ Visit [https://nuvu.dev](https://nuvu.dev) for the SaaS version with continuous
|
|
|
342
364
|
|
|
343
365
|
```bash
|
|
344
366
|
# Clone the repository
|
|
345
|
-
git clone https://github.com/
|
|
367
|
+
git clone https://github.com/nuvudev/nuvu-scan.git
|
|
346
368
|
cd nuvu-scan
|
|
347
369
|
|
|
348
370
|
# Install uv (if not already installed)
|
|
@@ -445,7 +467,7 @@ git clone https://github.com/your-username/nuvu-scan.git
|
|
|
445
467
|
cd nuvu-scan
|
|
446
468
|
|
|
447
469
|
# Add upstream remote
|
|
448
|
-
git remote add upstream https://github.com/
|
|
470
|
+
git remote add upstream https://github.com/nuvudev/nuvu-scan.git
|
|
449
471
|
```
|
|
450
472
|
|
|
451
473
|
### 2. Create a Branch
|
|
@@ -479,7 +501,7 @@ git push origin feature/your-feature-name
|
|
|
479
501
|
|
|
480
502
|
### 5. Create a Pull Request
|
|
481
503
|
|
|
482
|
-
- Go to https://github.com/
|
|
504
|
+
- Go to https://github.com/nuvudev/nuvu-scan
|
|
483
505
|
- Click "New Pull Request"
|
|
484
506
|
- Select your branch
|
|
485
507
|
- Fill out the PR template
|
|
@@ -550,7 +572,7 @@ Releases are automated via GitHub Actions:
|
|
|
550
572
|
```
|
|
551
573
|
|
|
552
574
|
2. **Create GitHub Release:**
|
|
553
|
-
- Go to https://github.com/
|
|
575
|
+
- Go to https://github.com/nuvudev/nuvu-scan/releases
|
|
554
576
|
- Click "Draft a new release"
|
|
555
577
|
- Select the tag
|
|
556
578
|
- Add release notes
|
|
@@ -31,6 +31,28 @@ pip install nuvu-scan
|
|
|
31
31
|
|
|
32
32
|
## Usage
|
|
33
33
|
|
|
34
|
+
### Optional: Push results to Nuvu Cloud
|
|
35
|
+
|
|
36
|
+
Nuvu Scan is fully open-source and runs standalone — no account required.
|
|
37
|
+
If you want dashboards, team workflows, and long‑term history, you can optionally push results to Nuvu Cloud.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Push results to Nuvu Cloud (optional)
|
|
41
|
+
nuvu scan --provider aws --push --api-key your_nuvu_api_key
|
|
42
|
+
|
|
43
|
+
# Or use environment variable
|
|
44
|
+
export NUVU_API_KEY=your_nuvu_api_key
|
|
45
|
+
nuvu scan --provider aws --push
|
|
46
|
+
|
|
47
|
+
# Custom cloud URL (defaults to https://nuvu.dev)
|
|
48
|
+
nuvu scan --provider aws --push --nuvu-cloud-url https://nuvu.dev
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
What this means for open‑source users:
|
|
52
|
+
- You can keep everything local and export JSON/CSV/HTML.
|
|
53
|
+
- No cloud credentials are ever sent to Nuvu Cloud — only scan results.
|
|
54
|
+
- The data collected is identical whether you run locally or push.
|
|
55
|
+
|
|
34
56
|
### AWS Scanning
|
|
35
57
|
|
|
36
58
|
**Prerequisites:** Create an IAM user or role with the read-only policy from `aws-iam-policy.json`. See the [AWS Setup](#aws-v1---available-now) section below for detailed instructions.
|
|
@@ -304,7 +326,7 @@ Visit [https://nuvu.dev](https://nuvu.dev) for the SaaS version with continuous
|
|
|
304
326
|
|
|
305
327
|
```bash
|
|
306
328
|
# Clone the repository
|
|
307
|
-
git clone https://github.com/
|
|
329
|
+
git clone https://github.com/nuvudev/nuvu-scan.git
|
|
308
330
|
cd nuvu-scan
|
|
309
331
|
|
|
310
332
|
# Install uv (if not already installed)
|
|
@@ -407,7 +429,7 @@ git clone https://github.com/your-username/nuvu-scan.git
|
|
|
407
429
|
cd nuvu-scan
|
|
408
430
|
|
|
409
431
|
# Add upstream remote
|
|
410
|
-
git remote add upstream https://github.com/
|
|
432
|
+
git remote add upstream https://github.com/nuvudev/nuvu-scan.git
|
|
411
433
|
```
|
|
412
434
|
|
|
413
435
|
### 2. Create a Branch
|
|
@@ -441,7 +463,7 @@ git push origin feature/your-feature-name
|
|
|
441
463
|
|
|
442
464
|
### 5. Create a Pull Request
|
|
443
465
|
|
|
444
|
-
- Go to https://github.com/
|
|
466
|
+
- Go to https://github.com/nuvudev/nuvu-scan
|
|
445
467
|
- Click "New Pull Request"
|
|
446
468
|
- Select your branch
|
|
447
469
|
- Fill out the PR template
|
|
@@ -512,7 +534,7 @@ Releases are automated via GitHub Actions:
|
|
|
512
534
|
```
|
|
513
535
|
|
|
514
536
|
2. **Create GitHub Release:**
|
|
515
|
-
- Go to https://github.com/
|
|
537
|
+
- Go to https://github.com/nuvudev/nuvu-scan/releases
|
|
516
538
|
- Click "Draft a new release"
|
|
517
539
|
- Select the tag
|
|
518
540
|
- Add release notes
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- Go to PyPI → Account Settings → API tokens
|
|
9
9
|
- Add a new "Trusted Publisher"
|
|
10
10
|
- Select "GitHub" as the publisher
|
|
11
|
-
- Repository: `
|
|
11
|
+
- Repository: `nuvudev/nuvu-scan`
|
|
12
12
|
- Workflow filename: `.github/workflows/publish.yml`
|
|
13
13
|
- Environment: (leave empty for default)
|
|
14
14
|
|
|
@@ -101,7 +101,7 @@ git push origin v1.3.2
|
|
|
101
101
|
|
|
102
102
|
If you need to create a release manually:
|
|
103
103
|
|
|
104
|
-
1. Go to https://github.com/
|
|
104
|
+
1. Go to https://github.com/nuvudev/nuvu-scan/releases
|
|
105
105
|
2. Click "Draft a new release"
|
|
106
106
|
3. Select tag: `v1.3.2` (or create new tag)
|
|
107
107
|
4. Title: `v1.3.2`
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
Scan command for Nuvu CLI.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import json
|
|
5
6
|
import os
|
|
6
7
|
import sys
|
|
7
8
|
from datetime import datetime
|
|
9
|
+
from urllib.error import HTTPError, URLError
|
|
10
|
+
from urllib.request import Request, urlopen
|
|
8
11
|
|
|
9
12
|
import click
|
|
10
13
|
|
|
@@ -83,6 +86,23 @@ from ..formatters.json import JSONFormatter
|
|
|
83
86
|
"--gcp-project",
|
|
84
87
|
help="GCP project ID (default: from service account key or GOOGLE_CLOUD_PROJECT env var)",
|
|
85
88
|
)
|
|
89
|
+
@click.option(
|
|
90
|
+
"--push",
|
|
91
|
+
is_flag=True,
|
|
92
|
+
help="Push scan results to Nuvu Cloud (requires API key)",
|
|
93
|
+
)
|
|
94
|
+
@click.option(
|
|
95
|
+
"--nuvu-cloud-url",
|
|
96
|
+
envvar="NUVU_CLOUD_URL",
|
|
97
|
+
default="https://nuvu.dev",
|
|
98
|
+
show_default=True,
|
|
99
|
+
help="Nuvu Cloud base URL",
|
|
100
|
+
)
|
|
101
|
+
@click.option(
|
|
102
|
+
"--api-key",
|
|
103
|
+
envvar="NUVU_API_KEY",
|
|
104
|
+
help="Nuvu Cloud API key (from dashboard account settings)",
|
|
105
|
+
)
|
|
86
106
|
def scan_command(
|
|
87
107
|
provider: str,
|
|
88
108
|
output_format: str,
|
|
@@ -98,6 +118,9 @@ def scan_command(
|
|
|
98
118
|
role_duration_seconds: int,
|
|
99
119
|
gcp_credentials: str | None,
|
|
100
120
|
gcp_project: str | None,
|
|
121
|
+
push: bool,
|
|
122
|
+
nuvu_cloud_url: str | None,
|
|
123
|
+
api_key: str | None,
|
|
101
124
|
):
|
|
102
125
|
"""Scan cloud provider for data assets."""
|
|
103
126
|
|
|
@@ -255,3 +278,42 @@ def scan_command(
|
|
|
255
278
|
with open(output_file, "w") as f:
|
|
256
279
|
f.write(content)
|
|
257
280
|
click.echo(f"Report written to {output_file}", err=True)
|
|
281
|
+
|
|
282
|
+
if push:
|
|
283
|
+
if not nuvu_cloud_url:
|
|
284
|
+
click.echo("Error: --nuvu-cloud-url or NUVU_CLOUD_URL is required for --push", err=True)
|
|
285
|
+
sys.exit(1)
|
|
286
|
+
if not api_key:
|
|
287
|
+
click.echo("Error: --api-key or NUVU_API_KEY is required for --push", err=True)
|
|
288
|
+
sys.exit(1)
|
|
289
|
+
|
|
290
|
+
payload = json.loads(JSONFormatter().format(result))
|
|
291
|
+
payload["scan_regions"] = list(region) if region else None
|
|
292
|
+
payload["scan_all_regions"] = False if region else True
|
|
293
|
+
|
|
294
|
+
import_url = nuvu_cloud_url.rstrip("/") + "/api/scans/import"
|
|
295
|
+
request = Request(
|
|
296
|
+
import_url,
|
|
297
|
+
data=json.dumps(payload).encode("utf-8"),
|
|
298
|
+
headers={
|
|
299
|
+
"Content-Type": "application/json",
|
|
300
|
+
"Authorization": f"Bearer {api_key}",
|
|
301
|
+
},
|
|
302
|
+
method="POST",
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
try:
|
|
306
|
+
with urlopen(request) as response:
|
|
307
|
+
response_body = response.read().decode("utf-8")
|
|
308
|
+
click.echo(f"Scan uploaded to Nuvu Cloud: {response.status}", err=True)
|
|
309
|
+
if response_body:
|
|
310
|
+
click.echo(response_body, err=True)
|
|
311
|
+
except HTTPError as e:
|
|
312
|
+
error_body = e.read().decode("utf-8")
|
|
313
|
+
click.echo(f"Failed to upload scan: {e.code} {e.reason}", err=True)
|
|
314
|
+
if error_body:
|
|
315
|
+
click.echo(error_body, err=True)
|
|
316
|
+
sys.exit(1)
|
|
317
|
+
except URLError as e:
|
|
318
|
+
click.echo(f"Failed to upload scan: {e.reason}", err=True)
|
|
319
|
+
sys.exit(1)
|
|
@@ -33,6 +33,8 @@ class AWSScanner(CloudProviderScan):
|
|
|
33
33
|
def __init__(self, config: ScanConfig):
|
|
34
34
|
super().__init__(config)
|
|
35
35
|
self.session = self._create_session()
|
|
36
|
+
if not self.config.regions:
|
|
37
|
+
self.config.regions = self._resolve_regions()
|
|
36
38
|
self.collectors = self._initialize_collectors()
|
|
37
39
|
self.cost_explorer = CostExplorerCollector(self.session, self.config.regions)
|
|
38
40
|
|
|
@@ -177,6 +179,18 @@ class AWSScanner(CloudProviderScan):
|
|
|
177
179
|
except ClientError as e:
|
|
178
180
|
raise ValueError(f"Failed to assume role {role_arn}: {str(e)}")
|
|
179
181
|
|
|
182
|
+
def _resolve_regions(self) -> list[str]:
|
|
183
|
+
"""Resolve regions to scan. If none provided, scan all enabled regions."""
|
|
184
|
+
try:
|
|
185
|
+
ec2 = self.session.client("ec2", region_name="us-east-1")
|
|
186
|
+
response = ec2.describe_regions(AllRegions=False)
|
|
187
|
+
regions = [region["RegionName"] for region in response.get("Regions", [])]
|
|
188
|
+
if regions:
|
|
189
|
+
return regions
|
|
190
|
+
except Exception:
|
|
191
|
+
pass
|
|
192
|
+
return ["us-east-1"]
|
|
193
|
+
|
|
180
194
|
def _get_account_id(self) -> str:
|
|
181
195
|
"""Get AWS account ID from STS get_caller_identity."""
|
|
182
196
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nuvu-scan"
|
|
3
|
-
version = "1.3.
|
|
3
|
+
version = "1.3.8"
|
|
4
4
|
description = "Multi-Cloud Data Asset Control - CLI tool for discovering and analyzing cloud data infrastructure"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -53,9 +53,9 @@ dev = [
|
|
|
53
53
|
|
|
54
54
|
[project.urls]
|
|
55
55
|
Homepage = "https://nuvu.dev"
|
|
56
|
-
Documentation = "https://github.com/
|
|
57
|
-
Repository = "https://github.com/
|
|
58
|
-
Issues = "https://github.com/
|
|
56
|
+
Documentation = "https://github.com/nuvudev/nuvu-scan#readme"
|
|
57
|
+
Repository = "https://github.com/nuvudev/nuvu-scan"
|
|
58
|
+
Issues = "https://github.com/nuvudev/nuvu-scan/issues"
|
|
59
59
|
|
|
60
60
|
[project.scripts]
|
|
61
61
|
nuvu = "nuvu_scan.cli.main:cli"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nuvu_scan-1.3.7 → nuvu_scan-1.3.8}/nuvu_scan/core/providers/aws/collectors/cost_explorer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|