bucket-scanner 0.12.0__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 (58) hide show
  1. bucket_scanner-0.12.0/LICENSE +21 -0
  2. bucket_scanner-0.12.0/PKG-INFO +372 -0
  3. bucket_scanner-0.12.0/README.md +335 -0
  4. bucket_scanner-0.12.0/pyproject.toml +75 -0
  5. bucket_scanner-0.12.0/setup.cfg +4 -0
  6. bucket_scanner-0.12.0/src/bucket_scanner/__init__.py +3 -0
  7. bucket_scanner-0.12.0/src/bucket_scanner/auth.py +156 -0
  8. bucket_scanner-0.12.0/src/bucket_scanner/aws/__init__.py +0 -0
  9. bucket_scanner-0.12.0/src/bucket_scanner/aws/iam.py +71 -0
  10. bucket_scanner-0.12.0/src/bucket_scanner/aws/s3.py +104 -0
  11. bucket_scanner-0.12.0/src/bucket_scanner/chains.py +107 -0
  12. bucket_scanner-0.12.0/src/bucket_scanner/checks.py +397 -0
  13. bucket_scanner-0.12.0/src/bucket_scanner/cli.py +638 -0
  14. bucket_scanner-0.12.0/src/bucket_scanner/cloud.py +24 -0
  15. bucket_scanner-0.12.0/src/bucket_scanner/config.py +281 -0
  16. bucket_scanner-0.12.0/src/bucket_scanner/diff.py +153 -0
  17. bucket_scanner-0.12.0/src/bucket_scanner/doctor.py +93 -0
  18. bucket_scanner-0.12.0/src/bucket_scanner/explain.py +158 -0
  19. bucket_scanner-0.12.0/src/bucket_scanner/fixture.py +47 -0
  20. bucket_scanner-0.12.0/src/bucket_scanner/gate.py +133 -0
  21. bucket_scanner-0.12.0/src/bucket_scanner/models.py +117 -0
  22. bucket_scanner-0.12.0/src/bucket_scanner/notify.py +107 -0
  23. bucket_scanner-0.12.0/src/bucket_scanner/probe.py +51 -0
  24. bucket_scanner-0.12.0/src/bucket_scanner/report/__init__.py +0 -0
  25. bucket_scanner-0.12.0/src/bucket_scanner/report/human.py +96 -0
  26. bucket_scanner-0.12.0/src/bucket_scanner/report/json_report.py +9 -0
  27. bucket_scanner-0.12.0/src/bucket_scanner/report/prometheus.py +52 -0
  28. bucket_scanner-0.12.0/src/bucket_scanner/report/sarif.py +93 -0
  29. bucket_scanner-0.12.0/src/bucket_scanner/s3_common.py +96 -0
  30. bucket_scanner-0.12.0/src/bucket_scanner/scan.py +351 -0
  31. bucket_scanner-0.12.0/src/bucket_scanner/scope.py +5 -0
  32. bucket_scanner-0.12.0/src/bucket_scanner/secrets.py +161 -0
  33. bucket_scanner-0.12.0/src/bucket_scanner/serve.py +121 -0
  34. bucket_scanner-0.12.0/src/bucket_scanner/terraform.py +233 -0
  35. bucket_scanner-0.12.0/src/bucket_scanner/tracefuse.py +61 -0
  36. bucket_scanner-0.12.0/src/bucket_scanner/yc/__init__.py +0 -0
  37. bucket_scanner-0.12.0/src/bucket_scanner/yc/management.py +63 -0
  38. bucket_scanner-0.12.0/src/bucket_scanner/yc/s3.py +45 -0
  39. bucket_scanner-0.12.0/src/bucket_scanner.egg-info/PKG-INFO +372 -0
  40. bucket_scanner-0.12.0/src/bucket_scanner.egg-info/SOURCES.txt +56 -0
  41. bucket_scanner-0.12.0/src/bucket_scanner.egg-info/dependency_links.txt +1 -0
  42. bucket_scanner-0.12.0/src/bucket_scanner.egg-info/entry_points.txt +2 -0
  43. bucket_scanner-0.12.0/src/bucket_scanner.egg-info/requires.txt +15 -0
  44. bucket_scanner-0.12.0/src/bucket_scanner.egg-info/top_level.txt +1 -0
  45. bucket_scanner-0.12.0/tests/test_aws.py +297 -0
  46. bucket_scanner-0.12.0/tests/test_azure.py +81 -0
  47. bucket_scanner-0.12.0/tests/test_checks.py +148 -0
  48. bucket_scanner-0.12.0/tests/test_ci_profiles.py +74 -0
  49. bucket_scanner-0.12.0/tests/test_cli.py +22 -0
  50. bucket_scanner-0.12.0/tests/test_gate.py +206 -0
  51. bucket_scanner-0.12.0/tests/test_integration.py +135 -0
  52. bucket_scanner-0.12.0/tests/test_package.py +16 -0
  53. bucket_scanner-0.12.0/tests/test_profiles.py +162 -0
  54. bucket_scanner-0.12.0/tests/test_scanner.py +109 -0
  55. bucket_scanner-0.12.0/tests/test_security.py +57 -0
  56. bucket_scanner-0.12.0/tests/test_serve.py +83 -0
  57. bucket_scanner-0.12.0/tests/test_terraform.py +67 -0
  58. bucket_scanner-0.12.0/tests/test_v03.py +119 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FounderB
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.4
2
+ Name: bucket-scanner
3
+ Version: 0.12.0
4
+ Summary: Declared vs real — Object Storage security scanner (Yandex Cloud + AWS S3 + Azure preview)
5
+ Author: FounderB
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/FounderB/BucketScanner
8
+ Project-URL: Repository, https://github.com/FounderB/BucketScanner
9
+ Project-URL: Issues, https://github.com/FounderB/BucketScanner/issues
10
+ Keywords: yandex-cloud,aws,s3,object-storage,bucket-scanner,security,cspm,devsecops,sarif
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Security
18
+ Classifier: Topic :: System :: Systems Administration
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: boto3>=1.34
23
+ Requires-Dist: click>=8.1
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: pyjwt[crypto]>=2.8
26
+ Requires-Dist: pydantic>=2.7
27
+ Requires-Dist: rich>=13.7
28
+ Provides-Extra: dev
29
+ Requires-Dist: bandit>=1.7; extra == "dev"
30
+ Requires-Dist: build>=1.2; extra == "dev"
31
+ Requires-Dist: pip-audit>=2.7; extra == "dev"
32
+ Requires-Dist: pytest>=8.2; extra == "dev"
33
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.5; extra == "dev"
35
+ Requires-Dist: twine>=5.0; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ <p align="center">
39
+ <img src="assets/bucket-scanner-icon.png" alt="Bucket Scanner" width="160" height="160"/>
40
+ </p>
41
+
42
+ <h1 align="center">Bucket Scanner</h1>
43
+
44
+ <p align="center">
45
+ <strong>Declared vs real.</strong> Object Storage security scanner (Yandex Cloud + AWS S3 + Azure preview).<br/>
46
+ What you configured · what ACL allows · what the internet can actually reach.
47
+ </p>
48
+
49
+ <p align="center">
50
+ <a href="https://github.com/FounderB/BucketScanner/actions"><img src="https://img.shields.io/github/actions/workflow/status/FounderB/BucketScanner/ci.yml?branch=main&label=CI&style=flat-square" alt="CI"/></a>
51
+ <img src="https://img.shields.io/badge/python-3.11%2B-2ee6a6?style=flat-square" alt="Python 3.11+"/>
52
+ <img src="https://img.shields.io/badge/Yandex%20Cloud-Object%20Storage-5282FF?style=flat-square" alt="Yandex Cloud"/>
53
+ <img src="https://img.shields.io/badge/AWS-S3-FF9900?style=flat-square" alt="AWS S3"/>
54
+ <img src="https://img.shields.io/badge/SARIF-2.1.0-2ee6a6?style=flat-square" alt="SARIF 2.1.0"/>
55
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-5eead4?style=flat-square" alt="MIT"/></a>
56
+ <img src="https://img.shields.io/badge/scan-metadata%20default-darkgrey?style=flat-square" alt="Metadata default"/>
57
+ </p>
58
+
59
+ <p align="center">
60
+ <a href="https://github.com/FounderB/FluxTap">FluxTap</a> ·
61
+ <a href="https://github.com/FounderB/Tracefuse">Tracefuse</a> ·
62
+ <a href="https://github.com/FounderB/Timeforge">Timeforge</a> ·
63
+ <a href="https://github.com/FounderB/SignShield">SignShield</a> ·
64
+ <b>Bucket Scanner</b>
65
+ </p>
66
+
67
+ ---
68
+
69
+ ## Why
70
+
71
+ Buckets drift. ACL says `private`, policy leaks `public-read`. Versioning is off, logging never enabled, a service account key outlived three rotations — and nobody noticed until exfil.
72
+
73
+ Bucket Scanner walks your **Object Storage** (Yandex Cloud by default, **AWS S3** optional) and surfaces gaps between **what you declare** and **what actually ships**:
74
+
75
+ | You declare | Bucket Scanner checks |
76
+ |-------------|----------------------|
77
+ | Private bucket | Anonymous `HEAD` / list probe |
78
+ | Encryption at rest | Server-side encryption flags per bucket |
79
+ | Audit trail | Access logging enabled |
80
+ | Ransomware resilience | Versioning + lifecycle sanity |
81
+ | Least privilege | SA bindings → blast radius chains |
82
+
83
+ Metadata scan by default. Optional live probe proves reachability — **without downloading object bodies**.
84
+
85
+ ```
86
+ ╔══════════════════════════════════════════════════════════╗
87
+ ║ BUCKET SCANNER ║
88
+ ║ declared vs real · object storage truth ║
89
+ ╚══════════════════════════════════════════════════════════╝
90
+
91
+ score 42 ████████░░░░░░░░░░░░
92
+ CRIT 1 HIGH 4 MED 7 LOW 2 INFO 3
93
+
94
+ CHAIN public-read + no-logging + stale-sa-key → silent exfil path
95
+ ```
96
+
97
+ Part of the **FounderB security stack**: [Tracefuse](https://github.com/FounderB/Tracefuse) watches what you ship · [FluxTap](https://github.com/FounderB/FluxTap) watches the wire · **Bucket Scanner** watches what you store.
98
+
99
+ ---
100
+
101
+ ## Install
102
+
103
+ **From PyPI** (recommended):
104
+
105
+ ```bash
106
+ pip install bucket-scanner
107
+ bucket-scanner --help
108
+ ```
109
+
110
+ **From source** (development):
111
+
112
+ ```bash
113
+ git clone https://github.com/FounderB/BucketScanner.git
114
+ cd BucketScanner
115
+ python3 -m venv .venv && source .venv/bin/activate
116
+ pip install -e ".[dev]"
117
+ make hooks # install local git author guard
118
+ ```
119
+
120
+ See [docs/PYPI.md](docs/PYPI.md) for version pins and maintainer publishing.
121
+
122
+ **Requirements:** Python **3.11+**, Yandex Cloud credentials (default) or AWS credentials (`--cloud aws`). See [docs/AWS.md](docs/AWS.md).
123
+
124
+ ---
125
+
126
+ ## AWS S3 (optional)
127
+
128
+ ```bash
129
+ export AWS_REGION=us-east-1
130
+ bucket-scanner scan --cloud aws
131
+ bucket-scanner scan --cloud aws --fixture examples/demo-vulnerable/fixture-aws.toml
132
+ bucket-scanner doctor --cloud aws
133
+ ```
134
+
135
+ ## Azure Blob (fixture-only preview)
136
+
137
+ ```bash
138
+ bucket-scanner scan --cloud azure --fixture examples/demo-vulnerable/fixture-azure.toml
139
+ bucket-scanner explain azure/container-public-access
140
+ ```
141
+
142
+ Live Azure inventory is planned; see [docs/AZURE.md](docs/AZURE.md).
143
+
144
+ ---
145
+
146
+ ## 60-second wow
147
+
148
+ All values under `examples/demo-vulnerable/` are labeled **FAKE / EXAMPLE**.
149
+
150
+ ```bash
151
+ # Offline demo — no cloud credentials required
152
+ bucket-scanner scan --fixture examples/demo-vulnerable/fixture.toml
153
+ bucket-scanner scan --fixture examples/demo-vulnerable/fixture.toml --json
154
+ bucket-scanner scan --fixture examples/demo-vulnerable/fixture.toml \
155
+ --sarif /tmp/bucket-scanner.sarif --fail-on high
156
+
157
+ bucket-scanner scan --fixture examples/demo-vulnerable/fixture.toml \
158
+ --repo examples/demo-vulnerable/repo \
159
+ --tracefuse-report examples/demo-vulnerable/tracefuse-report.json \
160
+ --prometheus /tmp/bucket-scanner.prom
161
+
162
+ # Prometheus + continuous monitoring
163
+ bucket-scanner serve --fixture examples/demo-vulnerable/fixture.toml --addr 127.0.0.1:9090
164
+
165
+ # Prove public exposure (anonymous probe, no object download)
166
+ bucket-scanner scan --folder-id b1gxxxxxxxxxx --probe
167
+ ```
168
+
169
+ Expect findings across **acl**, **policy**, **encryption**, **logging**, **versioning**, **lifecycle**, **iam**, and **chains**. Exit `1` when policy fails; exit `2` on tool error.
170
+
171
+ ---
172
+
173
+ ## Quick start
174
+
175
+ ```bash
176
+ export YC_TOKEN=$(yc iam create-token) # or YC_SERVICE_ACCOUNT_KEY_FILE
177
+ export YC_CLOUD_ID=b1g...
178
+ export YC_FOLDER_ID=b1g...
179
+
180
+ bucket-scanner scan --folder-id "$YC_FOLDER_ID"
181
+ bucket-scanner scan --folder-id "$YC_FOLDER_ID" --probe --fail-on high
182
+ bucket-scanner doctor # creds, scopes, API reachability
183
+ bucket-scanner explain acl/public-read # remediation + why
184
+ ```
185
+
186
+ > **Probe mode** sends unauthenticated HTTP requests to bucket endpoints to verify real-world exposure. It never downloads object payloads — only checks reachability metadata.
187
+
188
+ ---
189
+
190
+ ## Features
191
+
192
+ | Detector | What it catches |
193
+ |----------|-----------------|
194
+ | **acl** | `public-read`, `public-read-write`, world-open grants |
195
+ | **policy** | Bucket policy statements wider than intent |
196
+ | **encryption** | Missing default encryption / SSE gaps |
197
+ | **logging** | No access logs on sensitive buckets |
198
+ | **versioning** | Versioning disabled on prod-like buckets |
199
+ | **lifecycle** | Aggressive expiration, incomplete multipart cleanup |
200
+ | **iam** | Over-broad SA roles, long-lived static keys |
201
+ | **chains** | Compound risk: public + no logs + no versioning + stale key |
202
+
203
+ Also: health score, `bucket-scanner init` → `.bucket-scanner.toml`, `doctor` / `explain`, severity overrides, quiet mode for CI, SARIF 2.1.0 for GitHub Code Scanning, **`diff`** for Terraform drift.
204
+
205
+ ### Terraform drift
206
+
207
+ ```bash
208
+ bucket-scanner diff examples/demo-vulnerable/terraform \
209
+ --fixture examples/demo-vulnerable/fixture.toml
210
+
211
+ bucket-scanner scan --folder-id b1g... --terraform ./infra/storage/
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Why not the console?
217
+
218
+ | | YC Console / manual checklist | Bucket Scanner |
219
+ |---|---|---|
220
+ | Scope | One bucket at a time | Whole folder · repeatable |
221
+ | Proof | ACL text says private | **`--probe` proves** anonymous reachability |
222
+ | Output | Screenshots in tickets | **Redacted** human / JSON / SARIF |
223
+ | Policy | Spreadsheet | `--fail-on high` · GitHub Action |
224
+ | Chains | Siloed findings | **Misconfig graphs** — why it hurts together |
225
+ | Drift | Point-in-time | CI on every PR · scheduled scans |
226
+
227
+ Use Bucket Scanner when you need one gate that answers **“what does this folder *actually* risk?”** — not just “is there a public ACL string somewhere?”
228
+
229
+ ---
230
+
231
+ ## CLI
232
+
233
+ ```bash
234
+ bucket-scanner init [--force] [path] # write .bucket-scanner.toml
235
+ bucket-scanner doctor # creds, folder access, API health
236
+ bucket-scanner explain <rule-id> # remediation (e.g. acl/public-read)
237
+ bucket-scanner scan --folder-id ID # human report
238
+ bucket-scanner scan --folder-id ID --json # JSON to stdout
239
+ bucket-scanner scan --folder-id ID --sarif out.sarif --fail-on high
240
+ bucket-scanner scan --folder-id ID --baseline baselines/prod.json --fail-on new
241
+ bucket-scanner scan --folder-id ID --write-baseline baselines/prod.json
242
+ bucket-scanner scan --folder-id ID --probe # + anonymous reachability checks
243
+ bucket-scanner inspect BUCKET # single-bucket deep report
244
+ bucket-scanner chain --sa-id ID # blast radius from one SA
245
+ bucket-scanner diff PATH # Terraform vs live/fixture
246
+ bucket-scanner serve --addr 127.0.0.1:9090 # /metrics + /health
247
+ bucket-scanner list --folder-id ID # inventory summary
248
+ ```
249
+
250
+ **Exit codes:** `0` clean / below threshold · `1` policy fail · `2` tool error.
251
+
252
+ Default `fail_on` in config is `high` (overridable via `--fail-on` or `.bucket-scanner.toml`).
253
+
254
+ ---
255
+
256
+ ## Configuration
257
+
258
+ `bucket-scanner init` writes `.bucket-scanner.toml`:
259
+
260
+ ```toml
261
+ [scan]
262
+ folder_id = "b1gxxxxxxxxxx"
263
+ fail_on = "high"
264
+ probe = false
265
+
266
+ [scan.ignore_buckets]
267
+ names = ["public-assets-cdn"]
268
+
269
+ [[scan.severity_overrides]]
270
+ rule = "versioning/disabled"
271
+ severity = "medium"
272
+ ```
273
+
274
+ See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for full reference.
275
+
276
+ ---
277
+
278
+ ## Architecture
279
+
280
+ ```mermaid
281
+ flowchart LR
282
+ CLI["CLI<br/>scan · inspect · chain · doctor"] --> CFG[".bucket-scanner.toml"]
283
+ CFG --> SCAN["scan::run_scan"]
284
+ SCAN --> YC["YC Object Storage API<br/>metadata only"]
285
+ SCAN --> PROBE["probe::anonymous<br/>optional HEAD/list"]
286
+ YC --> DET["checks::*"]
287
+ PROBE --> DET
288
+ DET --> CHAIN["chains::compose"]
289
+ CHAIN --> OUT["report<br/>human · json · sarif"]
290
+ ```
291
+
292
+ Details: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) · [docs/CHECKS.md](docs/CHECKS.md)
293
+
294
+ ---
295
+
296
+ ## GitHub Actions
297
+
298
+ Minimal scan + SARIF upload. Full guide: [docs/GITHUB_ACTION.md](docs/GITHUB_ACTION.md).
299
+
300
+ ```yaml
301
+ name: bucket-scanner
302
+ on:
303
+ pull_request:
304
+ push:
305
+ branches: [main]
306
+ schedule:
307
+ - cron: "0 6 * * *"
308
+
309
+ permissions:
310
+ contents: read
311
+ security-events: write
312
+
313
+ jobs:
314
+ scan:
315
+ runs-on: ubuntu-latest
316
+ steps:
317
+ - uses: actions/checkout@v4
318
+ - uses: actions/setup-python@v5
319
+ with:
320
+ python-version: "3.11"
321
+ - run: pip install .
322
+ - name: Scan YC folder
323
+ env:
324
+ YC_TOKEN: ${{ secrets.YC_TOKEN }}
325
+ YC_FOLDER_ID: ${{ secrets.YC_FOLDER_ID }}
326
+ run: |
327
+ bucket-scanner scan --folder-id "$YC_FOLDER_ID" \
328
+ --sarif bucket-scanner.sarif --fail-on high -q
329
+ - name: Upload SARIF
330
+ if: always()
331
+ uses: github/codeql-action/upload-sarif@v3
332
+ with:
333
+ sarif_file: bucket-scanner.sarif
334
+ ```
335
+
336
+ ---
337
+
338
+ ## Security promises
339
+
340
+ - **Metadata by default** — list buckets, ACLs, policies, settings; no bulk object download.
341
+ - **Probe is opt-in** — anonymous HTTP checks only when you pass `--probe`.
342
+ - **Redaction** — SA key fragments, tokens, and sensitive URLs redacted in all report formats.
343
+ - **Offline fixtures** — `examples/demo-vulnerable/` uses clearly labeled **FAKE/EXAMPLE** values only.
344
+
345
+ See [SECURITY.md](SECURITY.md) and [docs/AUDIT.md](docs/AUDIT.md).
346
+
347
+ ---
348
+
349
+ ## Roadmap
350
+
351
+ - [x] Tracefuse hook — leaked `YC_*` in repo → cross-finding
352
+ - [x] Prometheus exporter + Grafana dashboard
353
+ - [x] Scheduled drift alerts (Telegram / webhook)
354
+ - [x] AWS S3 backend (optional second cloud)
355
+ - [x] Multi-region AWS inventory (per-bucket region resolution)
356
+ - [x] Scheduled scan profiles in config
357
+ - [x] CI/CD profile workflows (Action + scheduled matrix)
358
+ - [x] Baseline/delta + suppressions for production CI gates
359
+ - [x] Security hardening + audit docs (v0.11)
360
+ - [x] PyPI package (`pip install bucket-scanner`)
361
+ - [ ] Azure Blob live scan
362
+ - [ ] GCS backend
363
+
364
+ ---
365
+
366
+ ## License
367
+
368
+ MIT © FounderB — [LICENSE](LICENSE).
369
+
370
+ ## Contributing
371
+
372
+ [CONTRIBUTING.md](CONTRIBUTING.md) · [CHANGELOG.md](CHANGELOG.md)