cloud-audit 0.1.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.
- cloud_audit-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +75 -0
- cloud_audit-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- cloud_audit-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +47 -0
- cloud_audit-0.1.0/.github/dependabot.yml +18 -0
- cloud_audit-0.1.0/.github/pull_request_template.md +18 -0
- cloud_audit-0.1.0/.github/workflows/ci.yml +56 -0
- cloud_audit-0.1.0/.github/workflows/release.yml +41 -0
- cloud_audit-0.1.0/.gitignore +43 -0
- cloud_audit-0.1.0/CHANGELOG.md +30 -0
- cloud_audit-0.1.0/CLAUDE.md +89 -0
- cloud_audit-0.1.0/CODEOWNERS +4 -0
- cloud_audit-0.1.0/CODE_OF_CONDUCT.md +40 -0
- cloud_audit-0.1.0/CONTRIBUTING.md +166 -0
- cloud_audit-0.1.0/Dockerfile +15 -0
- cloud_audit-0.1.0/LICENSE +21 -0
- cloud_audit-0.1.0/PKG-INFO +273 -0
- cloud_audit-0.1.0/README.md +231 -0
- cloud_audit-0.1.0/ROADMAP.md +663 -0
- cloud_audit-0.1.0/SECURITY.md +46 -0
- cloud_audit-0.1.0/pyproject.toml +80 -0
- cloud_audit-0.1.0/src/cloud_audit/__init__.py +3 -0
- cloud_audit-0.1.0/src/cloud_audit/__main__.py +5 -0
- cloud_audit-0.1.0/src/cloud_audit/cli.py +229 -0
- cloud_audit-0.1.0/src/cloud_audit/models.py +120 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/__init__.py +1 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/__init__.py +5 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/__init__.py +1 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/ec2.py +132 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/eip.py +54 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/iam.py +194 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/rds.py +132 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/s3.py +145 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/checks/vpc.py +183 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/aws/provider.py +62 -0
- cloud_audit-0.1.0/src/cloud_audit/providers/base.py +29 -0
- cloud_audit-0.1.0/src/cloud_audit/py.typed +0 -0
- cloud_audit-0.1.0/src/cloud_audit/reports/__init__.py +1 -0
- cloud_audit-0.1.0/src/cloud_audit/reports/html.py +39 -0
- cloud_audit-0.1.0/src/cloud_audit/reports/templates/report.html.j2 +334 -0
- cloud_audit-0.1.0/src/cloud_audit/scanner.py +73 -0
- cloud_audit-0.1.0/tests/__init__.py +0 -0
- cloud_audit-0.1.0/tests/test_models.py +90 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug in cloud-audit
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for reporting a bug! Please fill out the information below.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: description
|
|
12
|
+
attributes:
|
|
13
|
+
label: What happened?
|
|
14
|
+
description: A clear description of the bug.
|
|
15
|
+
placeholder: Describe the bug...
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: expected
|
|
21
|
+
attributes:
|
|
22
|
+
label: Expected behavior
|
|
23
|
+
description: What did you expect to happen?
|
|
24
|
+
placeholder: I expected...
|
|
25
|
+
|
|
26
|
+
- type: textarea
|
|
27
|
+
id: reproduce
|
|
28
|
+
attributes:
|
|
29
|
+
label: Steps to reproduce
|
|
30
|
+
description: Minimal steps to reproduce the issue.
|
|
31
|
+
placeholder: |
|
|
32
|
+
1. Run `cloud-audit scan --provider aws`
|
|
33
|
+
2. ...
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: logs
|
|
39
|
+
attributes:
|
|
40
|
+
label: Error output
|
|
41
|
+
description: Paste any error messages or relevant output.
|
|
42
|
+
render: shell
|
|
43
|
+
|
|
44
|
+
- type: input
|
|
45
|
+
id: version
|
|
46
|
+
attributes:
|
|
47
|
+
label: cloud-audit version
|
|
48
|
+
description: "Run `cloud-audit version` to find out."
|
|
49
|
+
placeholder: "0.1.0"
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
52
|
+
|
|
53
|
+
- type: dropdown
|
|
54
|
+
id: python
|
|
55
|
+
attributes:
|
|
56
|
+
label: Python version
|
|
57
|
+
options:
|
|
58
|
+
- "3.10"
|
|
59
|
+
- "3.11"
|
|
60
|
+
- "3.12"
|
|
61
|
+
- "3.13"
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
|
|
65
|
+
- type: dropdown
|
|
66
|
+
id: os
|
|
67
|
+
attributes:
|
|
68
|
+
label: Operating system
|
|
69
|
+
options:
|
|
70
|
+
- Linux
|
|
71
|
+
- macOS
|
|
72
|
+
- Windows
|
|
73
|
+
- Docker
|
|
74
|
+
validations:
|
|
75
|
+
required: true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new check or feature
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for suggesting an improvement! Please describe your idea below.
|
|
9
|
+
|
|
10
|
+
- type: dropdown
|
|
11
|
+
id: type
|
|
12
|
+
attributes:
|
|
13
|
+
label: Type of request
|
|
14
|
+
options:
|
|
15
|
+
- New AWS check
|
|
16
|
+
- CLI improvement
|
|
17
|
+
- Report improvement
|
|
18
|
+
- New output format
|
|
19
|
+
- New cloud provider
|
|
20
|
+
- Other
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
|
|
24
|
+
- type: textarea
|
|
25
|
+
id: problem
|
|
26
|
+
attributes:
|
|
27
|
+
label: Problem or use case
|
|
28
|
+
description: What problem does this solve? Why is it needed?
|
|
29
|
+
placeholder: I want this because...
|
|
30
|
+
validations:
|
|
31
|
+
required: true
|
|
32
|
+
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: solution
|
|
35
|
+
attributes:
|
|
36
|
+
label: Proposed solution
|
|
37
|
+
description: How should it work? Be as specific as possible.
|
|
38
|
+
placeholder: It should...
|
|
39
|
+
validations:
|
|
40
|
+
required: true
|
|
41
|
+
|
|
42
|
+
- type: textarea
|
|
43
|
+
id: alternatives
|
|
44
|
+
attributes:
|
|
45
|
+
label: Alternatives considered
|
|
46
|
+
description: Have you considered any alternatives?
|
|
47
|
+
placeholder: I also considered...
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
labels:
|
|
8
|
+
- "dependencies"
|
|
9
|
+
open-pull-requests-limit: 5
|
|
10
|
+
|
|
11
|
+
- package-ecosystem: "github-actions"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "weekly"
|
|
15
|
+
labels:
|
|
16
|
+
- "dependencies"
|
|
17
|
+
- "ci"
|
|
18
|
+
open-pull-requests-limit: 5
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## What
|
|
2
|
+
|
|
3
|
+
<!-- Brief description of the change -->
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
<!-- What problem does this solve? Link to issue if applicable -->
|
|
8
|
+
|
|
9
|
+
Closes #
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
|
|
13
|
+
- [ ] `ruff check src/ tests/` passes
|
|
14
|
+
- [ ] `ruff format --check src/ tests/` passes
|
|
15
|
+
- [ ] `mypy src/` passes
|
|
16
|
+
- [ ] `pytest -v` passes
|
|
17
|
+
- [ ] README updated (if adding a new check)
|
|
18
|
+
- [ ] CHANGELOG updated
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint:
|
|
14
|
+
name: Lint & Format
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
- run: pip install ruff
|
|
22
|
+
- run: ruff check src/ tests/
|
|
23
|
+
- run: ruff format --check src/ tests/
|
|
24
|
+
|
|
25
|
+
typecheck:
|
|
26
|
+
name: Type Check
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
- uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.12"
|
|
33
|
+
- run: pip install -e ".[dev]"
|
|
34
|
+
- run: mypy src/
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
strategy:
|
|
40
|
+
matrix:
|
|
41
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: ${{ matrix.python-version }}
|
|
47
|
+
- run: pip install -e ".[dev]"
|
|
48
|
+
- run: pytest -v --tb=short --cov=cloud_audit --cov-report=term-missing
|
|
49
|
+
|
|
50
|
+
docker:
|
|
51
|
+
name: Docker Build
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
- run: docker build -t cloud-audit:test .
|
|
56
|
+
- run: docker run --rm cloud-audit:test version
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distribution
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
- run: pip install build
|
|
21
|
+
- run: python -m build
|
|
22
|
+
- uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: dist
|
|
25
|
+
path: dist/
|
|
26
|
+
|
|
27
|
+
publish:
|
|
28
|
+
name: Publish to PyPI
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment:
|
|
32
|
+
name: pypi
|
|
33
|
+
url: https://pypi.org/p/cloud-audit
|
|
34
|
+
permissions:
|
|
35
|
+
id-token: write
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/download-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: dist
|
|
40
|
+
path: dist/
|
|
41
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
*.egg
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
.eggs/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
|
|
15
|
+
# Environment variables
|
|
16
|
+
.env
|
|
17
|
+
.env.local
|
|
18
|
+
|
|
19
|
+
# IDE
|
|
20
|
+
.vscode/
|
|
21
|
+
.idea/
|
|
22
|
+
*.swp
|
|
23
|
+
*.swo
|
|
24
|
+
|
|
25
|
+
# Testing
|
|
26
|
+
.pytest_cache/
|
|
27
|
+
.coverage
|
|
28
|
+
htmlcov/
|
|
29
|
+
coverage.xml
|
|
30
|
+
|
|
31
|
+
# Type checking
|
|
32
|
+
.mypy_cache/
|
|
33
|
+
|
|
34
|
+
# Linting
|
|
35
|
+
.ruff_cache/
|
|
36
|
+
|
|
37
|
+
# Reports (generated output, not source)
|
|
38
|
+
*.html
|
|
39
|
+
!src/cloud_audit/reports/templates/*.html.j2
|
|
40
|
+
|
|
41
|
+
# OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-03-03
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Initial release
|
|
15
|
+
- CLI interface with `scan` and `version` commands
|
|
16
|
+
- 17 AWS security, cost, and reliability checks:
|
|
17
|
+
- **IAM:** Root MFA, user MFA, access key rotation, unused access keys
|
|
18
|
+
- **S3:** Public buckets, encryption at rest, versioning
|
|
19
|
+
- **EC2:** Public AMIs, unencrypted EBS volumes, stopped instances
|
|
20
|
+
- **VPC:** Default VPC usage, open security groups, flow logs
|
|
21
|
+
- **RDS:** Public instances, encryption at rest, Multi-AZ
|
|
22
|
+
- **EIP:** Unattached Elastic IPs
|
|
23
|
+
- Health score (0-100) based on finding severity
|
|
24
|
+
- HTML report with dark-mode design
|
|
25
|
+
- JSON output for CI/CD integration
|
|
26
|
+
- Docker image support
|
|
27
|
+
- Rich terminal UI with progress bar and color-coded findings
|
|
28
|
+
|
|
29
|
+
[Unreleased]: https://github.com/gebalamariusz/cloud-audit/compare/v0.1.0...HEAD
|
|
30
|
+
[0.1.0]: https://github.com/gebalamariusz/cloud-audit/releases/tag/v0.1.0
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install (editable, with dev deps)
|
|
9
|
+
pip install -e ".[dev]"
|
|
10
|
+
|
|
11
|
+
# Run CLI
|
|
12
|
+
cloud-audit scan --provider aws --profile <name> --regions eu-central-1
|
|
13
|
+
cloud-audit version
|
|
14
|
+
|
|
15
|
+
# Tests
|
|
16
|
+
pytest -v
|
|
17
|
+
pytest tests/test_models.py -v # single file
|
|
18
|
+
pytest tests/test_models.py::test_name -v # single test
|
|
19
|
+
|
|
20
|
+
# Lint
|
|
21
|
+
ruff check src/ tests/
|
|
22
|
+
ruff format --check src/ tests/
|
|
23
|
+
|
|
24
|
+
# Type check
|
|
25
|
+
mypy src/
|
|
26
|
+
|
|
27
|
+
# Docker
|
|
28
|
+
docker build -t cloud-audit .
|
|
29
|
+
docker run cloud-audit version
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Architecture
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
src/cloud_audit/
|
|
36
|
+
├── cli.py # Typer CLI entry point (scan, version commands)
|
|
37
|
+
├── models.py # Pydantic models: Finding, CheckResult, ScanSummary, ScanReport
|
|
38
|
+
├── scanner.py # Orchestrator: runs checks with Rich progress bar → ScanReport
|
|
39
|
+
├── providers/
|
|
40
|
+
│ ├── base.py # BaseProvider ABC (get_account_id, get_checks, get_provider_name)
|
|
41
|
+
│ └── aws/
|
|
42
|
+
│ ├── provider.py # AWSProvider: boto3 session, region handling, check loading
|
|
43
|
+
│ └── checks/ # One module per AWS service (iam, s3, ec2, vpc, rds, eip)
|
|
44
|
+
└── reports/
|
|
45
|
+
├── html.py # Jinja2 renderer
|
|
46
|
+
└── templates/ # report.html.j2 (self-contained dark-mode HTML)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Pipeline flow
|
|
50
|
+
|
|
51
|
+
`CLI (cli.py)` → `Scanner (scanner.py)` → `Provider.get_checks()` → execute each check → aggregate into `ScanReport` → `_print_summary()` + optional HTML/JSON output.
|
|
52
|
+
|
|
53
|
+
### Check registration pattern
|
|
54
|
+
|
|
55
|
+
Each check module in `providers/aws/checks/` exports a `get_checks(provider)` function that returns `list[partial(check_fn, provider)]` with `.category` attribute attached to each partial for filtering.
|
|
56
|
+
|
|
57
|
+
### Global vs. regional checks
|
|
58
|
+
|
|
59
|
+
- **Global** (single API call): IAM, S3
|
|
60
|
+
- **Regional** (loops `provider.regions`): EC2, RDS, VPC, EIP
|
|
61
|
+
|
|
62
|
+
### Health score
|
|
63
|
+
|
|
64
|
+
Starts at 100, subtracts per finding: CRITICAL=20, HIGH=10, MEDIUM=5, LOW=2. Floor at 0.
|
|
65
|
+
|
|
66
|
+
### Error handling
|
|
67
|
+
|
|
68
|
+
- Each check is wrapped in try/except — errors populate `CheckResult.error` without halting the scan.
|
|
69
|
+
- CLI detects `all_errored` state (e.g., expired credentials) and shows "SCAN FAILED" panel with fix suggestions instead of a misleading score.
|
|
70
|
+
|
|
71
|
+
## Adding a new check
|
|
72
|
+
|
|
73
|
+
1. Create or edit a module in `src/cloud_audit/providers/aws/checks/`.
|
|
74
|
+
2. Write a function `check_something(provider: AWSProvider) -> CheckResult`.
|
|
75
|
+
3. Add it to the module's `get_checks()` return list with `.category` set.
|
|
76
|
+
4. Register the module in `AWSProvider._CHECK_MODULES` list in `provider.py`.
|
|
77
|
+
5. Update `README.md` checks table.
|
|
78
|
+
|
|
79
|
+
## Adding a new provider
|
|
80
|
+
|
|
81
|
+
1. Create `src/cloud_audit/providers/<name>/provider.py` implementing `BaseProvider`.
|
|
82
|
+
2. Add the provider import to `cli.py`'s `scan()` command.
|
|
83
|
+
|
|
84
|
+
## Key conventions
|
|
85
|
+
|
|
86
|
+
- Python 3.10+ compatibility required (no `type` aliases, no `X | Y` in runtime annotations — use `from __future__ import annotations`).
|
|
87
|
+
- Pydantic v2 models — immutable by default.
|
|
88
|
+
- Ruff for linting (line-length=120, strict security rules enabled).
|
|
89
|
+
- `S101` (assert) is ignored in ruff config for test compatibility.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
* Using welcoming and inclusive language
|
|
17
|
+
* Being respectful of differing viewpoints and experiences
|
|
18
|
+
* Gracefully accepting constructive criticism
|
|
19
|
+
* Focusing on what is best for the community
|
|
20
|
+
|
|
21
|
+
Examples of unacceptable behavior:
|
|
22
|
+
|
|
23
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
24
|
+
* Public or private harassment
|
|
25
|
+
* Publishing others' private information without explicit permission
|
|
26
|
+
* Other conduct which could reasonably be considered inappropriate
|
|
27
|
+
|
|
28
|
+
## Enforcement
|
|
29
|
+
|
|
30
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
31
|
+
reported to the project maintainer at [kontakt@haitmg.pl](mailto:kontakt@haitmg.pl).
|
|
32
|
+
|
|
33
|
+
All complaints will be reviewed and investigated and will result in a response
|
|
34
|
+
that is deemed necessary and appropriate to the circumstances.
|
|
35
|
+
|
|
36
|
+
## Attribution
|
|
37
|
+
|
|
38
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
39
|
+
version 2.1, available at
|
|
40
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Contributing to cloud-audit
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to cloud-audit! This document provides guidelines and instructions for contributing.
|
|
4
|
+
|
|
5
|
+
## How to Contribute
|
|
6
|
+
|
|
7
|
+
1. **Fork** the repository
|
|
8
|
+
2. **Create a branch** from `main` for your changes
|
|
9
|
+
3. **Make your changes** following the guidelines below
|
|
10
|
+
4. **Run checks** to ensure code quality
|
|
11
|
+
5. **Submit a pull request** to `main`
|
|
12
|
+
|
|
13
|
+
## Development Setup
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/<your-username>/cloud-audit.git
|
|
17
|
+
cd cloud-audit
|
|
18
|
+
pip install -e ".[dev]"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Code Quality Checks
|
|
22
|
+
|
|
23
|
+
Before submitting a PR, make sure all checks pass:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Lint
|
|
27
|
+
ruff check src/ tests/
|
|
28
|
+
|
|
29
|
+
# Format
|
|
30
|
+
ruff format --check src/ tests/
|
|
31
|
+
|
|
32
|
+
# Type check
|
|
33
|
+
mypy src/
|
|
34
|
+
|
|
35
|
+
# Tests
|
|
36
|
+
pytest -v
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Adding a New AWS Check
|
|
40
|
+
|
|
41
|
+
This is the most common contribution. Follow these steps:
|
|
42
|
+
|
|
43
|
+
### 1. Create or edit a check module
|
|
44
|
+
|
|
45
|
+
Check modules live in `src/cloud_audit/providers/aws/checks/`. Each module covers one AWS service.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
# src/cloud_audit/providers/aws/checks/cloudtrail.py
|
|
49
|
+
|
|
50
|
+
from __future__ import annotations
|
|
51
|
+
|
|
52
|
+
from functools import partial
|
|
53
|
+
from typing import TYPE_CHECKING
|
|
54
|
+
|
|
55
|
+
from cloud_audit.models import Category, CheckResult, Finding, Severity
|
|
56
|
+
|
|
57
|
+
if TYPE_CHECKING:
|
|
58
|
+
from cloud_audit.providers.aws.provider import AWSProvider
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def check_cloudtrail_enabled(provider: AWSProvider) -> CheckResult:
|
|
62
|
+
"""Check if CloudTrail is enabled with multi-region logging."""
|
|
63
|
+
result = CheckResult(
|
|
64
|
+
check_id="aws-ct-001",
|
|
65
|
+
check_name="CloudTrail enabled",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
client = provider.session.client("cloudtrail")
|
|
69
|
+
trails = client.describe_trails()["trailList"]
|
|
70
|
+
result.resources_scanned = len(trails)
|
|
71
|
+
|
|
72
|
+
# ... check logic ...
|
|
73
|
+
|
|
74
|
+
return result
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_checks(provider: AWSProvider) -> list[partial[CheckResult]]:
|
|
78
|
+
checks = [
|
|
79
|
+
partial(check_cloudtrail_enabled, provider),
|
|
80
|
+
]
|
|
81
|
+
for check in checks:
|
|
82
|
+
check.category = Category.SECURITY # type: ignore[attr-defined]
|
|
83
|
+
return checks
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Register the module
|
|
87
|
+
|
|
88
|
+
Add the module name to `_CHECK_MODULES` in `src/cloud_audit/providers/aws/provider.py`:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
_CHECK_MODULES = [
|
|
92
|
+
"iam", "s3", "ec2", "vpc", "rds", "eip",
|
|
93
|
+
"cloudtrail", # <-- add here
|
|
94
|
+
]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Add tests
|
|
98
|
+
|
|
99
|
+
Write tests using moto for AWS mocking:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
# tests/unit/aws/test_cloudtrail.py
|
|
103
|
+
|
|
104
|
+
import boto3
|
|
105
|
+
from moto import mock_aws
|
|
106
|
+
|
|
107
|
+
def test_cloudtrail_enabled_pass():
|
|
108
|
+
"""CloudTrail enabled should produce no findings."""
|
|
109
|
+
with mock_aws():
|
|
110
|
+
# Setup: create a trail
|
|
111
|
+
client = boto3.client("cloudtrail", region_name="eu-central-1")
|
|
112
|
+
client.create_trail(Name="main", S3BucketName="logs")
|
|
113
|
+
client.start_logging(Name="main")
|
|
114
|
+
|
|
115
|
+
# Run check and assert no findings
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def test_cloudtrail_enabled_fail():
|
|
119
|
+
"""No CloudTrail should produce a CRITICAL finding."""
|
|
120
|
+
with mock_aws():
|
|
121
|
+
# No trails created
|
|
122
|
+
# Run check and assert finding exists
|
|
123
|
+
...
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 4. Update documentation
|
|
127
|
+
|
|
128
|
+
- Add the check to the table in `README.md`
|
|
129
|
+
- Add the check to `CHANGELOG.md` under `[Unreleased]`
|
|
130
|
+
|
|
131
|
+
### 5. Submit
|
|
132
|
+
|
|
133
|
+
Run all checks, then open a pull request.
|
|
134
|
+
|
|
135
|
+
## Check Design Guidelines
|
|
136
|
+
|
|
137
|
+
Every check in cloud-audit must follow these principles:
|
|
138
|
+
|
|
139
|
+
1. **High-signal only** — Would an attacker exploit this? If not, don't add it.
|
|
140
|
+
2. **Clear severity** — CRITICAL means "fix today", LOW means "nice to have".
|
|
141
|
+
3. **Actionable recommendation** — Tell the user exactly what to do, not "consider enabling encryption".
|
|
142
|
+
4. **Tested** — Every check needs at least one PASS and one FAIL test case.
|
|
143
|
+
|
|
144
|
+
## Code Conventions
|
|
145
|
+
|
|
146
|
+
- **Python 3.10+** — Use `from __future__ import annotations` in every file
|
|
147
|
+
- **Pydantic v2** — All data models use Pydantic with immutable config
|
|
148
|
+
- **Ruff** — Handles both linting and formatting (config in `pyproject.toml`)
|
|
149
|
+
- **mypy strict** — All code must pass `mypy --strict`
|
|
150
|
+
- **Line length** — 120 characters max
|
|
151
|
+
|
|
152
|
+
## Reporting Bugs
|
|
153
|
+
|
|
154
|
+
Use the [bug report template](https://github.com/gebalamariusz/cloud-audit/issues/new?template=bug_report.yml) on GitHub.
|
|
155
|
+
|
|
156
|
+
## Suggesting Features
|
|
157
|
+
|
|
158
|
+
Use the [feature request template](https://github.com/gebalamariusz/cloud-audit/issues/new?template=feature_request.yml) on GitHub.
|
|
159
|
+
|
|
160
|
+
## Security Vulnerabilities
|
|
161
|
+
|
|
162
|
+
**Do not open a public issue.** See [SECURITY.md](SECURITY.md) for responsible disclosure instructions.
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
By contributing, you agree that your contributions will be licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FROM python:3.12-slim AS base
|
|
2
|
+
|
|
3
|
+
LABEL maintainer="Mariusz Gebala <kontakt@haitmg.pl>"
|
|
4
|
+
LABEL org.opencontainers.image.source="https://github.com/gebalamariusz/cloud-audit"
|
|
5
|
+
LABEL org.opencontainers.image.description="Scan your cloud infrastructure for security, cost, and reliability issues."
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY pyproject.toml README.md ./
|
|
10
|
+
COPY src/ src/
|
|
11
|
+
|
|
12
|
+
RUN pip install --no-cache-dir .
|
|
13
|
+
|
|
14
|
+
ENTRYPOINT ["cloud-audit"]
|
|
15
|
+
CMD ["scan", "--help"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mariusz Gebala / HAIT
|
|
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.
|