rhada 0.0.1__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.
- rhada-0.0.1/.github/workflows/ci.yml +39 -0
- rhada-0.0.1/.github/workflows/publish.yml +49 -0
- rhada-0.0.1/.gitignore +39 -0
- rhada-0.0.1/PKG-INFO +160 -0
- rhada-0.0.1/README.md +120 -0
- rhada-0.0.1/pyproject.toml +112 -0
- rhada-0.0.1/src/rhada/__init__.py +58 -0
- rhada-0.0.1/src/rhada/auditor.py +145 -0
- rhada-0.0.1/src/rhada/cli.py +392 -0
- rhada-0.0.1/src/rhada/compliance.py +447 -0
- rhada-0.0.1/src/rhada/dist.py +1131 -0
- rhada-0.0.1/src/rhada/elf.py +1095 -0
- rhada-0.0.1/src/rhada/models.py +504 -0
- rhada-0.0.1/src/rhada/osv.py +397 -0
- rhada-0.0.1/src/rhada/pe.py +459 -0
- rhada-0.0.1/src/rhada/py.typed +1 -0
- rhada-0.0.1/src/rhada/reporter.py +211 -0
- rhada-0.0.1/src/rhada/sbom.py +460 -0
- rhada-0.0.1/src/rhada/spdx.py +1299 -0
- rhada-0.0.1/src/rhada/workspace.py +1260 -0
- rhada-0.0.1/tests/__init__.py +1 -0
- rhada-0.0.1/tests/helpers.py +504 -0
- rhada-0.0.1/tests/test_edge_cases.py +620 -0
- rhada-0.0.1/tests/test_elf_and_dist.py +210 -0
- rhada-0.0.1/tests/test_native_provenance.py +769 -0
- rhada-0.0.1/tests/test_sbom_and_cli.py +318 -0
- rhada-0.0.1/tests/test_spdx_and_compliance.py +194 -0
- rhada-0.0.1/tests/test_windows_and_scientific.py +1103 -0
- rhada-0.0.1/tests/test_workspace_and_osv.py +289 -0
- rhada-0.0.1/uv.lock +954 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }})
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, windows-latest]
|
|
17
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
18
|
+
env:
|
|
19
|
+
UV_PYTHON: ${{ matrix.python-version }}
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v5
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
|
|
29
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
30
|
+
run: uv python install ${{ matrix.python-version }}
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: uv sync --frozen
|
|
34
|
+
|
|
35
|
+
- name: Run linter (ruff)
|
|
36
|
+
run: uv run ruff check src tests
|
|
37
|
+
|
|
38
|
+
- name: Run test suite (pytest)
|
|
39
|
+
run: uv run pytest -v
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build distribution artefacts
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v5
|
|
17
|
+
with:
|
|
18
|
+
enable-cache: true
|
|
19
|
+
|
|
20
|
+
- name: Build sdist and wheel
|
|
21
|
+
run: uv build
|
|
22
|
+
|
|
23
|
+
- name: Store distribution artefacts
|
|
24
|
+
uses: actions/upload-artifact@v4
|
|
25
|
+
with:
|
|
26
|
+
name: python-package-distributions
|
|
27
|
+
path: dist/
|
|
28
|
+
|
|
29
|
+
pypi-publish:
|
|
30
|
+
name: Upload release to PyPI
|
|
31
|
+
needs: [build]
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
environment:
|
|
34
|
+
name: pypi
|
|
35
|
+
url: https://pypi.org/p/rhada
|
|
36
|
+
permissions:
|
|
37
|
+
id-token: write # Mandatory for PyPI Trusted Publishing (OIDC)
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- name: Download distribution artefacts
|
|
41
|
+
uses: actions/download-artifact@v4
|
|
42
|
+
with:
|
|
43
|
+
name: python-package-distributions
|
|
44
|
+
path: dist/
|
|
45
|
+
|
|
46
|
+
- name: Publish to PyPI
|
|
47
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
48
|
+
with:
|
|
49
|
+
packages-dir: dist/
|
rhada-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# Virtual environments
|
|
28
|
+
.venv/
|
|
29
|
+
venv/
|
|
30
|
+
ENV/
|
|
31
|
+
env/
|
|
32
|
+
|
|
33
|
+
# Unit test / coverage / linter caches
|
|
34
|
+
.coverage
|
|
35
|
+
.coverage.*
|
|
36
|
+
htmlcov/
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.ruff_cache/
|
|
39
|
+
.mypy_cache/
|
rhada-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: rhada
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Legal compliance, SBOM generation, binary linkage verification, and security vulnerability auditor for Python source workspaces and compiled Nuitka/PyInstaller distributions.
|
|
5
|
+
Project-URL: Homepage, https://github.com/dcollison/rhada
|
|
6
|
+
Project-URL: Repository, https://github.com/dcollison/rhada
|
|
7
|
+
Project-URL: Issues, https://github.com/dcollison/rhada/issues
|
|
8
|
+
Author: Rhada DevSecOps Team
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
Keywords: compliance,cyclonedx,elf,nuitka,osv,pip-audit,pyinstaller,rhada,sbom,security,spdx,typer,uv,vulnerability
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: Intended Audience :: Legal Industry
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
25
|
+
Classifier: Topic :: System :: Software Distribution
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.11
|
|
28
|
+
Requires-Dist: cvss>=3.6
|
|
29
|
+
Requires-Dist: cyclonedx-python-lib>=11.12.0
|
|
30
|
+
Requires-Dist: defusedxml>=0.7.1
|
|
31
|
+
Requires-Dist: httpx>=0.27.0
|
|
32
|
+
Requires-Dist: license-expression>=30.4.4
|
|
33
|
+
Requires-Dist: packageurl-python>=0.17.6
|
|
34
|
+
Requires-Dist: packaging>=24.0
|
|
35
|
+
Requires-Dist: pip-audit>=2.10.1
|
|
36
|
+
Requires-Dist: pyelftools>=0.31
|
|
37
|
+
Requires-Dist: rich>=13.7.0
|
|
38
|
+
Requires-Dist: typer>=0.27.3
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# Rhada
|
|
42
|
+
|
|
43
|
+
Rhada is a compliance, Software Bill of Materials (SBOM), binary linkage, and security vulnerability auditor for Python source workspaces and compiled Linux distributions (Nuitka and PyInstaller).
|
|
44
|
+
|
|
45
|
+
## Overview
|
|
46
|
+
|
|
47
|
+
1. **Dual-Mode Operation**
|
|
48
|
+
- **Source Mode (default when `--dist` is omitted):** Inspects a `uv` workspace (`pyproject.toml`, `uv.lock`, and `.venv/lib/.../site-packages/*.dist-info`) to separate transitive runtime dependencies from development and build dependencies, extract SPDX licence metadata, and check for security advisories.
|
|
49
|
+
- **Compiled Distribution Mode (`--dist <path>`):** Audits Nuitka and PyInstaller artefacts, including standalone directories (`app.dist/`, `dist/app/`) and monolithic single-file binaries (`app.bin`). Identifies bundled Python modules (excluding build and test tools such as `pytest`, `ruff`, `mypy`, `nuitka`, and `pyinstaller`), inspects bundled native shared libraries (`.so`), and verifies ELF dynamic linkage.
|
|
50
|
+
|
|
51
|
+
2. **Legal and Licence Compliance**
|
|
52
|
+
- Parses and normalises `METADATA` licence headers, PEP 639 `License-Expression` fields, Trove classifiers, and verbatim licence texts into canonical SPDX identifiers and compound expressions (`MIT OR Apache-2.0`, `GPL-2.0-only AND BSD-3-Clause`) using `license-expression`.
|
|
53
|
+
- Categorises licence risk (`permissive`, `public-domain`, `weak-copyleft`, `strong-copyleft`, `proprietary`, `unknown`) and evaluates redistribution rules:
|
|
54
|
+
- Flags strong copyleft (`GPL-*`, `AGPL-*`, `SSPL-1.0`) obligations (`LIC-COP-STRONG`, `LIC-COP-NETWORK`).
|
|
55
|
+
- Detects LGPL relinking issues (`LIC-LGPL-MONOLITHIC`) when weak-copyleft libraries are statically compiled or embedded into monolithic binaries without dynamic `.so` relinking support.
|
|
56
|
+
- Generates a `THIRD_PARTY_NOTICES` attribution file containing component inventory, copyright notices, `NOTICE` / `AUTHORS` files, and verbatim licence texts.
|
|
57
|
+
|
|
58
|
+
3. **ELF Binary and Native Library Inspection**
|
|
59
|
+
- Parses 32-bit and 64-bit ELF executables and `.so` libraries via `pyelftools` with a `struct` fallback for stripped or header-truncated binaries.
|
|
60
|
+
- Extracts `DT_NEEDED`, `DT_SONAME`, `DT_RPATH`, `DT_RUNPATH`, `PT_INTERP`, exported symbols (`PyInit_*`, `modulecode_*`), and embedded library version strings (`OpenSSL`, `zlib`, `SQLite`, `libffi`, `gmp`, `readline`, etc.).
|
|
61
|
+
- Verifies whether each `DT_NEEDED` shared library is resolved within the distribution, satisfied by the baseline Linux/glibc ABI, or missing as an unbundled external dependency, and flags insecure RPATH/RUNPATH tokens.
|
|
62
|
+
|
|
63
|
+
4. **Security Vulnerability Auditing**
|
|
64
|
+
- Integrates `pip-audit` (`OsvService` and `ResolvedDependency`) alongside the OSV.dev batch API (`/v1/querybatch`) and advisory endpoints (`/v1/vulns/{id}`) for discovered Python packages and versioned native libraries.
|
|
65
|
+
- Calculates CVSS v3.0/v3.1 base scores using `cvss` and summarises findings by severity (`CRITICAL`, `HIGH`, `MEDIUM`, `LOW`) with fixed version recommendations.
|
|
66
|
+
|
|
67
|
+
5. **Standards-Compliant SBOMs and CLI Exit Codes**
|
|
68
|
+
- Generates **CycloneDX 1.5 JSON** (via `cyclonedx-python-lib` and `packageurl-python`) and **SPDX 2.3 JSON** SBOMs.
|
|
69
|
+
- Provides a typed CLI built with `typer` and deterministic exit codes for CI/CD enforcement.
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
Manage and install with [`uv`](https://docs.astral.sh/uv/):
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Install dependencies and synchronise virtual environment
|
|
77
|
+
uv sync
|
|
78
|
+
|
|
79
|
+
# Run via uv
|
|
80
|
+
uv run rhada --help
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## CLI Usage
|
|
84
|
+
|
|
85
|
+
### 1. Audit a Python / `uv` Source Workspace
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
uv run rhada --project . \
|
|
89
|
+
--sbom sbom.cdx.json \
|
|
90
|
+
--notices THIRD_PARTY_NOTICES
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2. Audit a Compiled Nuitka or PyInstaller Distribution
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Standalone directory (Nuitka .dist or PyInstaller folder)
|
|
97
|
+
uv run rhada --project . --dist ./build/app.dist \
|
|
98
|
+
--sbom dist-sbom.json \
|
|
99
|
+
--sbom-format cyclonedx \
|
|
100
|
+
--notices dist/THIRD_PARTY_NOTICES \
|
|
101
|
+
--fail-on-linkage
|
|
102
|
+
|
|
103
|
+
# Monolithic single-file binary (PyInstaller onefile or Nuitka onefile)
|
|
104
|
+
uv run rhada --project . --dist ./dist/app-linux-x86_64 \
|
|
105
|
+
--sbom dist-sbom.spdx.json \
|
|
106
|
+
--sbom-format spdx \
|
|
107
|
+
--notices dist/THIRD_PARTY_NOTICES
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Subcommands
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Generate SBOM to stdout or file
|
|
114
|
+
uv run rhada sbom --project . --format spdx --output sbom.spdx.json
|
|
115
|
+
|
|
116
|
+
# Generate THIRD_PARTY_NOTICES
|
|
117
|
+
uv run rhada notices --project . --dist ./build/app.dist --output THIRD_PARTY_NOTICES
|
|
118
|
+
|
|
119
|
+
# Inspect ELF binaries and DT_NEEDED linkage directly
|
|
120
|
+
uv run rhada inspect-elf ./build/app.dist
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Exit Codes
|
|
124
|
+
|
|
125
|
+
| Exit Code | Enum Name | Meaning |
|
|
126
|
+
| :---: | :--- | :--- |
|
|
127
|
+
| `0` | `OK` | Audit passed all security, licence, and binary linkage policies. |
|
|
128
|
+
| `1` | `VULNERABILITY_FAILURE` | One or more vulnerabilities met or exceeded `--fail-on-severity` (default: `high`). |
|
|
129
|
+
| `2` | `LICENSE_FAILURE` | One or more licence compliance findings met or exceeded `--fail-on-licence` / `--fail-on-license` (default: `high`). |
|
|
130
|
+
| `3` | `COMBINED_POLICY_FAILURE` | Both vulnerability and licence compliance thresholds were breached. |
|
|
131
|
+
| `4` | `LINKAGE_FAILURE` | `--fail-on-linkage` was set and unbundled external `DT_NEEDED` libraries or insecure RPATHs were found. |
|
|
132
|
+
| `5` | `USAGE_OR_IO_ERROR` | Invalid CLI arguments or unreadable target paths. |
|
|
133
|
+
|
|
134
|
+
### GitHub Actions CI Example
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
jobs:
|
|
138
|
+
compliance-and-security-gate:
|
|
139
|
+
runs-on: ubuntu-latest
|
|
140
|
+
steps:
|
|
141
|
+
- uses: actions/checkout@v4
|
|
142
|
+
- uses: astral-sh/setup-uv@v4
|
|
143
|
+
- name: Run Rhada Audit and Generate Release Artefacts
|
|
144
|
+
run: |
|
|
145
|
+
uv run rhada audit \
|
|
146
|
+
--project . \
|
|
147
|
+
--dist ./dist/my-service.dist \
|
|
148
|
+
--sbom ./dist/sbom.cdx.json \
|
|
149
|
+
--notices ./dist/THIRD_PARTY_NOTICES \
|
|
150
|
+
--report-json ./dist/rhada-report.json \
|
|
151
|
+
--fail-on-severity high \
|
|
152
|
+
--fail-on-licence high \
|
|
153
|
+
--fail-on-linkage
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Running Tests
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uv run pytest -v
|
|
160
|
+
```
|
rhada-0.0.1/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Rhada
|
|
2
|
+
|
|
3
|
+
Rhada is a compliance, Software Bill of Materials (SBOM), binary linkage, and security vulnerability auditor for Python source workspaces and compiled Linux distributions (Nuitka and PyInstaller).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
1. **Dual-Mode Operation**
|
|
8
|
+
- **Source Mode (default when `--dist` is omitted):** Inspects a `uv` workspace (`pyproject.toml`, `uv.lock`, and `.venv/lib/.../site-packages/*.dist-info`) to separate transitive runtime dependencies from development and build dependencies, extract SPDX licence metadata, and check for security advisories.
|
|
9
|
+
- **Compiled Distribution Mode (`--dist <path>`):** Audits Nuitka and PyInstaller artefacts, including standalone directories (`app.dist/`, `dist/app/`) and monolithic single-file binaries (`app.bin`). Identifies bundled Python modules (excluding build and test tools such as `pytest`, `ruff`, `mypy`, `nuitka`, and `pyinstaller`), inspects bundled native shared libraries (`.so`), and verifies ELF dynamic linkage.
|
|
10
|
+
|
|
11
|
+
2. **Legal and Licence Compliance**
|
|
12
|
+
- Parses and normalises `METADATA` licence headers, PEP 639 `License-Expression` fields, Trove classifiers, and verbatim licence texts into canonical SPDX identifiers and compound expressions (`MIT OR Apache-2.0`, `GPL-2.0-only AND BSD-3-Clause`) using `license-expression`.
|
|
13
|
+
- Categorises licence risk (`permissive`, `public-domain`, `weak-copyleft`, `strong-copyleft`, `proprietary`, `unknown`) and evaluates redistribution rules:
|
|
14
|
+
- Flags strong copyleft (`GPL-*`, `AGPL-*`, `SSPL-1.0`) obligations (`LIC-COP-STRONG`, `LIC-COP-NETWORK`).
|
|
15
|
+
- Detects LGPL relinking issues (`LIC-LGPL-MONOLITHIC`) when weak-copyleft libraries are statically compiled or embedded into monolithic binaries without dynamic `.so` relinking support.
|
|
16
|
+
- Generates a `THIRD_PARTY_NOTICES` attribution file containing component inventory, copyright notices, `NOTICE` / `AUTHORS` files, and verbatim licence texts.
|
|
17
|
+
|
|
18
|
+
3. **ELF Binary and Native Library Inspection**
|
|
19
|
+
- Parses 32-bit and 64-bit ELF executables and `.so` libraries via `pyelftools` with a `struct` fallback for stripped or header-truncated binaries.
|
|
20
|
+
- Extracts `DT_NEEDED`, `DT_SONAME`, `DT_RPATH`, `DT_RUNPATH`, `PT_INTERP`, exported symbols (`PyInit_*`, `modulecode_*`), and embedded library version strings (`OpenSSL`, `zlib`, `SQLite`, `libffi`, `gmp`, `readline`, etc.).
|
|
21
|
+
- Verifies whether each `DT_NEEDED` shared library is resolved within the distribution, satisfied by the baseline Linux/glibc ABI, or missing as an unbundled external dependency, and flags insecure RPATH/RUNPATH tokens.
|
|
22
|
+
|
|
23
|
+
4. **Security Vulnerability Auditing**
|
|
24
|
+
- Integrates `pip-audit` (`OsvService` and `ResolvedDependency`) alongside the OSV.dev batch API (`/v1/querybatch`) and advisory endpoints (`/v1/vulns/{id}`) for discovered Python packages and versioned native libraries.
|
|
25
|
+
- Calculates CVSS v3.0/v3.1 base scores using `cvss` and summarises findings by severity (`CRITICAL`, `HIGH`, `MEDIUM`, `LOW`) with fixed version recommendations.
|
|
26
|
+
|
|
27
|
+
5. **Standards-Compliant SBOMs and CLI Exit Codes**
|
|
28
|
+
- Generates **CycloneDX 1.5 JSON** (via `cyclonedx-python-lib` and `packageurl-python`) and **SPDX 2.3 JSON** SBOMs.
|
|
29
|
+
- Provides a typed CLI built with `typer` and deterministic exit codes for CI/CD enforcement.
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
Manage and install with [`uv`](https://docs.astral.sh/uv/):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Install dependencies and synchronise virtual environment
|
|
37
|
+
uv sync
|
|
38
|
+
|
|
39
|
+
# Run via uv
|
|
40
|
+
uv run rhada --help
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## CLI Usage
|
|
44
|
+
|
|
45
|
+
### 1. Audit a Python / `uv` Source Workspace
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv run rhada --project . \
|
|
49
|
+
--sbom sbom.cdx.json \
|
|
50
|
+
--notices THIRD_PARTY_NOTICES
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Audit a Compiled Nuitka or PyInstaller Distribution
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Standalone directory (Nuitka .dist or PyInstaller folder)
|
|
57
|
+
uv run rhada --project . --dist ./build/app.dist \
|
|
58
|
+
--sbom dist-sbom.json \
|
|
59
|
+
--sbom-format cyclonedx \
|
|
60
|
+
--notices dist/THIRD_PARTY_NOTICES \
|
|
61
|
+
--fail-on-linkage
|
|
62
|
+
|
|
63
|
+
# Monolithic single-file binary (PyInstaller onefile or Nuitka onefile)
|
|
64
|
+
uv run rhada --project . --dist ./dist/app-linux-x86_64 \
|
|
65
|
+
--sbom dist-sbom.spdx.json \
|
|
66
|
+
--sbom-format spdx \
|
|
67
|
+
--notices dist/THIRD_PARTY_NOTICES
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. Subcommands
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Generate SBOM to stdout or file
|
|
74
|
+
uv run rhada sbom --project . --format spdx --output sbom.spdx.json
|
|
75
|
+
|
|
76
|
+
# Generate THIRD_PARTY_NOTICES
|
|
77
|
+
uv run rhada notices --project . --dist ./build/app.dist --output THIRD_PARTY_NOTICES
|
|
78
|
+
|
|
79
|
+
# Inspect ELF binaries and DT_NEEDED linkage directly
|
|
80
|
+
uv run rhada inspect-elf ./build/app.dist
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Exit Codes
|
|
84
|
+
|
|
85
|
+
| Exit Code | Enum Name | Meaning |
|
|
86
|
+
| :---: | :--- | :--- |
|
|
87
|
+
| `0` | `OK` | Audit passed all security, licence, and binary linkage policies. |
|
|
88
|
+
| `1` | `VULNERABILITY_FAILURE` | One or more vulnerabilities met or exceeded `--fail-on-severity` (default: `high`). |
|
|
89
|
+
| `2` | `LICENSE_FAILURE` | One or more licence compliance findings met or exceeded `--fail-on-licence` / `--fail-on-license` (default: `high`). |
|
|
90
|
+
| `3` | `COMBINED_POLICY_FAILURE` | Both vulnerability and licence compliance thresholds were breached. |
|
|
91
|
+
| `4` | `LINKAGE_FAILURE` | `--fail-on-linkage` was set and unbundled external `DT_NEEDED` libraries or insecure RPATHs were found. |
|
|
92
|
+
| `5` | `USAGE_OR_IO_ERROR` | Invalid CLI arguments or unreadable target paths. |
|
|
93
|
+
|
|
94
|
+
### GitHub Actions CI Example
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
jobs:
|
|
98
|
+
compliance-and-security-gate:
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
- uses: astral-sh/setup-uv@v4
|
|
103
|
+
- name: Run Rhada Audit and Generate Release Artefacts
|
|
104
|
+
run: |
|
|
105
|
+
uv run rhada audit \
|
|
106
|
+
--project . \
|
|
107
|
+
--dist ./dist/my-service.dist \
|
|
108
|
+
--sbom ./dist/sbom.cdx.json \
|
|
109
|
+
--notices ./dist/THIRD_PARTY_NOTICES \
|
|
110
|
+
--report-json ./dist/rhada-report.json \
|
|
111
|
+
--fail-on-severity high \
|
|
112
|
+
--fail-on-licence high \
|
|
113
|
+
--fail-on-linkage
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Running Tests
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
uv run pytest -v
|
|
120
|
+
```
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rhada"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "Legal compliance, SBOM generation, binary linkage verification, and security vulnerability auditor for Python source workspaces and compiled Nuitka/PyInstaller distributions."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Rhada DevSecOps Team" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"rhada",
|
|
17
|
+
"sbom",
|
|
18
|
+
"compliance",
|
|
19
|
+
"security",
|
|
20
|
+
"vulnerability",
|
|
21
|
+
"osv",
|
|
22
|
+
"pip-audit",
|
|
23
|
+
"cyclonedx",
|
|
24
|
+
"spdx",
|
|
25
|
+
"nuitka",
|
|
26
|
+
"pyinstaller",
|
|
27
|
+
"elf",
|
|
28
|
+
"typer",
|
|
29
|
+
"uv",
|
|
30
|
+
]
|
|
31
|
+
classifiers = [
|
|
32
|
+
"Development Status :: 5 - Production/Stable",
|
|
33
|
+
"Environment :: Console",
|
|
34
|
+
"Intended Audience :: Developers",
|
|
35
|
+
"Intended Audience :: Information Technology",
|
|
36
|
+
"Intended Audience :: Legal Industry",
|
|
37
|
+
"License :: OSI Approved :: Apache Software License",
|
|
38
|
+
"Operating System :: OS Independent",
|
|
39
|
+
"Programming Language :: Python :: 3",
|
|
40
|
+
"Programming Language :: Python :: 3.11",
|
|
41
|
+
"Programming Language :: Python :: 3.12",
|
|
42
|
+
"Programming Language :: Python :: 3.13",
|
|
43
|
+
"Programming Language :: Python :: 3.14",
|
|
44
|
+
"Topic :: Security",
|
|
45
|
+
"Topic :: Software Development :: Build Tools",
|
|
46
|
+
"Topic :: System :: Software Distribution",
|
|
47
|
+
"Typing :: Typed",
|
|
48
|
+
]
|
|
49
|
+
dependencies = [
|
|
50
|
+
"cvss>=3.6",
|
|
51
|
+
"cyclonedx-python-lib>=11.12.0",
|
|
52
|
+
"defusedxml>=0.7.1",
|
|
53
|
+
"httpx>=0.27.0",
|
|
54
|
+
"license-expression>=30.4.4",
|
|
55
|
+
"packageurl-python>=0.17.6",
|
|
56
|
+
"packaging>=24.0",
|
|
57
|
+
"pip-audit>=2.10.1",
|
|
58
|
+
"pyelftools>=0.31",
|
|
59
|
+
"rich>=13.7.0",
|
|
60
|
+
"typer>=0.27.3",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[project.scripts]
|
|
64
|
+
rhada = "rhada.cli:main"
|
|
65
|
+
|
|
66
|
+
[project.urls]
|
|
67
|
+
Homepage = "https://github.com/dcollison/rhada"
|
|
68
|
+
Repository = "https://github.com/dcollison/rhada"
|
|
69
|
+
Issues = "https://github.com/dcollison/rhada/issues"
|
|
70
|
+
|
|
71
|
+
[dependency-groups]
|
|
72
|
+
dev = [
|
|
73
|
+
"pytest>=8.0.0",
|
|
74
|
+
"pytest-cov>=5.0.0",
|
|
75
|
+
"ruff>=0.17.2",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.hatch.build.targets.wheel]
|
|
79
|
+
packages = ["src/rhada"]
|
|
80
|
+
|
|
81
|
+
[tool.pytest.ini_options]
|
|
82
|
+
testpaths = ["tests"]
|
|
83
|
+
pythonpath = ["src", "."]
|
|
84
|
+
addopts = "-q"
|
|
85
|
+
|
|
86
|
+
[tool.ruff]
|
|
87
|
+
target-version = "py311"
|
|
88
|
+
line-length = 120
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint]
|
|
91
|
+
select = [
|
|
92
|
+
"E",
|
|
93
|
+
"F",
|
|
94
|
+
"W",
|
|
95
|
+
"I",
|
|
96
|
+
"UP",
|
|
97
|
+
"B",
|
|
98
|
+
"SIM",
|
|
99
|
+
"RUF",
|
|
100
|
+
"PERF",
|
|
101
|
+
"FURB",
|
|
102
|
+
"PIE",
|
|
103
|
+
"BLE",
|
|
104
|
+
"S",
|
|
105
|
+
]
|
|
106
|
+
ignore = [
|
|
107
|
+
"E501",
|
|
108
|
+
"S101",
|
|
109
|
+
"S108",
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Rhada: Legal compliance, SBOM generation, and security auditor for Python and compiled distributions."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.0.1"
|
|
4
|
+
|
|
5
|
+
from rhada.auditor import compute_exit_code, run_audit
|
|
6
|
+
from rhada.elf import is_pe_file, parse_pe_binary
|
|
7
|
+
from rhada.models import (
|
|
8
|
+
AuditConfig,
|
|
9
|
+
AuditMode,
|
|
10
|
+
AuditReport,
|
|
11
|
+
BinaryInfo,
|
|
12
|
+
BinaryLinkageReport,
|
|
13
|
+
BundlerType,
|
|
14
|
+
ComplianceFinding,
|
|
15
|
+
Component,
|
|
16
|
+
ComponentScope,
|
|
17
|
+
ComponentType,
|
|
18
|
+
ConsoleFormat,
|
|
19
|
+
DistributionLayout,
|
|
20
|
+
ElfBinaryInfo,
|
|
21
|
+
ExitCode,
|
|
22
|
+
LicenseInfo,
|
|
23
|
+
LicenseRiskCategory,
|
|
24
|
+
LinkageIssue,
|
|
25
|
+
LinkageStatus,
|
|
26
|
+
SbomFormat,
|
|
27
|
+
Severity,
|
|
28
|
+
Vulnerability,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"AuditConfig",
|
|
33
|
+
"AuditMode",
|
|
34
|
+
"AuditReport",
|
|
35
|
+
"BinaryInfo",
|
|
36
|
+
"BinaryLinkageReport",
|
|
37
|
+
"BundlerType",
|
|
38
|
+
"ComplianceFinding",
|
|
39
|
+
"Component",
|
|
40
|
+
"ComponentScope",
|
|
41
|
+
"ComponentType",
|
|
42
|
+
"ConsoleFormat",
|
|
43
|
+
"DistributionLayout",
|
|
44
|
+
"ElfBinaryInfo",
|
|
45
|
+
"ExitCode",
|
|
46
|
+
"LicenseInfo",
|
|
47
|
+
"LicenseRiskCategory",
|
|
48
|
+
"LinkageIssue",
|
|
49
|
+
"LinkageStatus",
|
|
50
|
+
"SbomFormat",
|
|
51
|
+
"Severity",
|
|
52
|
+
"Vulnerability",
|
|
53
|
+
"__version__",
|
|
54
|
+
"compute_exit_code",
|
|
55
|
+
"is_pe_file",
|
|
56
|
+
"parse_pe_binary",
|
|
57
|
+
"run_audit",
|
|
58
|
+
]
|