Skip to content

Commit dd1b717

Browse files
committed
updated to include rhel9 cp39 builds & airgaps.
1 parent e555e63 commit dd1b717

6 files changed

Lines changed: 563 additions & 12 deletions

File tree

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
strategy:
2525
fail-fast: false
2626
matrix:
27-
python-version: ["3.13", "3.14"]
27+
python-version: ["3.9", "3.11", "3.13", "3.14"]
2828

2929
permissions:
3030
contents: read

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ RUN mkdir -p /app/data /app/output /app/config /app/logs && \
5757
chmod -R g=u /app
5858

5959
# Copy Python packages from builder
60-
COPY --from=builder --chown=1001:0 /opt/app-root/lib/python3.12/site-packages /opt/app-root/lib/python3.11/site-packages
60+
COPY --from=builder --chown=1001:0 /opt/app-root/lib/python3.12/site-packages /opt/app-root/lib/python3.12/site-packages
6161

6262
# Copy console script from builder
6363
COPY --from=builder --chown=1001:0 /opt/app-root/bin/policy-audit /opt/app-root/bin/policy-audit

INSTALL.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Installation
2+
3+
## Standard Install (from GitHub release)
4+
5+
Download the wheel from the
6+
[GitHub Releases](https://github.com/cs-shadowbq/falcon-policy-scoring/releases)
7+
page:
8+
9+
```bash
10+
pip install falcon_policy_scoring-1.8.0-py3-none-any.whl
11+
```
12+
13+
Or install directly from the repository:
14+
15+
```bash
16+
pip install git+https://github.com/cs-shadowbq/falcon-policy-scoring.git@v1.8.0
17+
```
18+
19+
## Development Install
20+
21+
```bash
22+
git clone https://github.com/cs-shadowbq/falcon-policy-scoring.git
23+
cd falcon-policy-scoring
24+
pip install -e ".[dev,test]"
25+
```
26+
27+
## Airgapped Install (RHEL 9 x86_64)
28+
29+
For disconnected/air-gapped environments without internet access on the target host.
30+
31+
### Download the Bundle
32+
33+
From the [GitHub Releases](https://github.com/cs-shadowbq/falcon-policy-scoring/releases)
34+
page, download the appropriate airgap bundle:
35+
36+
| Bundle | Target |
37+
|--------|--------|
38+
| `falcon-policy-scoring-*-airgap-rhel9-cp39-x86_64.tar.gz` | Python 3.9 (RHEL 9 default) |
39+
| `falcon-policy-scoring-*-airgap-rhel9-cp311-x86_64.tar.gz` | Python 3.11 |
40+
41+
### Install on Target
42+
43+
Transfer the tarball to the airgapped host:
44+
45+
```bash
46+
tar xzf falcon-policy-scoring-*-airgap-rhel9-*.tar.gz
47+
cd falcon-policy-scoring-*-airgap-*/
48+
./install.sh
49+
```
50+
51+
The installer auto-detects whether `pip` is available and falls back to manual
52+
wheel extraction if not.
53+
54+
### Manual Install (no pip, no root)
55+
56+
If you need full control over where packages land:
57+
58+
```bash
59+
mkdir -p ~/pylibs
60+
for whl in wheels/*.whl; do unzip -q -o "$whl" -d ~/pylibs/; done
61+
export PYTHONPATH=~/pylibs:$PYTHONPATH
62+
python3 -m falcon_policy_scoring --help
63+
```
64+
65+
Add the `PYTHONPATH` export to your `~/.bashrc` to make it persistent.
66+
67+
### Building the Airgap Bundle Yourself
68+
69+
On a machine with internet access:
70+
71+
```bash
72+
# Build wheel + both Python 3.9 and 3.11 bundles
73+
make airgap
74+
75+
# Or target a specific Python version
76+
make airgap AIRGAP_PYTHON=39
77+
78+
# The script can also be run standalone
79+
./scripts/build-airgap.sh --python 39,311
80+
```
81+
82+
Outputs land in `dist/`:
83+
84+
```
85+
dist/
86+
├── falcon_policy_scoring-1.8.0-py3-none-any.whl
87+
├── falcon-policy-scoring-1.8.0.tar.gz
88+
├── falcon-policy-scoring-1.8.0-airgap-rhel9-cp39-x86_64.tar.gz
89+
└── falcon-policy-scoring-1.8.0-airgap-rhel9-cp311-x86_64.tar.gz
90+
```
91+
92+
Each airgap bundle contains:
93+
94+
- `wheels/` — all runtime dependency wheels pre-compiled for the target
95+
- `install.sh` — auto-installer (uses pip if available, falls back to unzip)
96+
- `sbom.cdx.json` — CycloneDX 1.5 SBOM listing all bundled components and versions
97+
- `README.md` — quick-start instructions
98+
99+
## Creating a GitHub Release
100+
101+
Build everything and push to GitHub in one step (requires `gh` CLI):
102+
103+
```bash
104+
make release
105+
```
106+
107+
This runs `dist` + `airgap` then uses `gh release create` to publish:
108+
109+
- The `.whl` (universal wheel)
110+
- The `.tar.gz` (sdist)
111+
- Both airgap bundles
112+
113+
### Prerequisites
114+
115+
- [GitHub CLI](https://cli.github.com/) installed and authenticated (`gh auth login`)
116+
- Git tag matching the version in `pyproject.toml` (e.g., `git tag v1.8.0 && git push --tags`)
117+
118+
### Manual Release Workflow
119+
120+
```bash
121+
# 1. Bump version in pyproject.toml
122+
# 2. Commit and tag
123+
git add pyproject.toml
124+
git commit -m "Release v1.8.0"
125+
git tag v1.8.0
126+
git push && git push --tags
127+
128+
# 3. Build and release
129+
make release
130+
```

Makefile

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: docs clean docs-serve install test test-coverage test-coverage-serve workflows run help requirements docker-build docker-test docker-push k8s-deploy k8s-delete run-daemon
1+
.PHONY: docs clean docs-serve install test test-coverage test-coverage-serve workflows run help requirements docker-build docker-test docker-push k8s-deploy k8s-delete run-daemon dist dist-clean airgap release
22

33
help:
44
@echo "Available Make Targets:"
@@ -22,6 +22,12 @@ help:
2222
@echo " install Install all dependencies"
2323
@echo " requirements Generate requirements.txt files from pyproject.toml"
2424
@echo ""
25+
@echo "Distribution Targets:"
26+
@echo " dist Build wheel and sdist"
27+
@echo " dist-clean Clean dist/ and build artifacts"
28+
@echo " airgap Build airgap bundles (RHEL 9 x86_64)"
29+
@echo " release Create GitHub release with all artifacts (via gh CLI)"
30+
@echo ""
2531
@echo "Daemon Mode Targets:"
2632
@echo " run-daemon Run daemon locally"
2733
@echo " docker-build Build Docker image [TAG=version]"
@@ -33,8 +39,13 @@ help:
3339
@echo "Environment Variables:"
3440
@echo " REGISTRY=registry.com Docker registry (required for push)"
3541
@echo " TAG=version Docker image tag (default: latest)"
42+
@echo " AIRGAP_PYTHON=39,311 Python versions for airgap bundles (default: 39,311)"
3643
@echo ""
3744
@echo "Examples:"
45+
@echo " make dist Build wheel"
46+
@echo " make airgap Build airgap bundles for Python 3.9 + 3.11"
47+
@echo " make airgap AIRGAP_PYTHON=39 Build only Python 3.9 bundle"
48+
@echo " make release Push dist + airgap to GitHub release"
3849
@echo " make docker-build TAG=v1.0.0"
3950
@echo " export REGISTRY=docker.io/myuser && make docker-push"
4051
@echo " REGISTRY=ghcr.io/org TAG=dev make docker-push"
@@ -53,7 +64,7 @@ docs:
5364
sphinx-apidoc -o docs/source src/falcon_policy_scoring
5465
cd docs && make html
5566

56-
clean:
67+
clean: dist-clean clean-test
5768
@rm -rf data/*.json data/*.db data/*.sqlite && echo 'Cleaned database files in data/'
5869
@rm -rf logs/*.log && echo 'Cleaned log files in logs/'
5970
@rm -f results.json && echo 'Cleaned results.json'
@@ -165,9 +176,77 @@ requirements:
165176
# REGISTRY=ghcr.io/myorg TAG=dev make docker-push
166177

167178
TAG ?= latest
179+
AIRGAP_PYTHON ?= 39,311
168180

169181
# Extract version from pyproject.toml
170-
VERSION := $(shell python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])" 2>/dev/null || echo "0.0.0")
182+
VERSION := $(shell python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])" 2>/dev/null || python3 -c "import tomli as tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])" 2>/dev/null || echo "0.0.0")
183+
184+
# --- Distribution targets ---
185+
186+
dist: dist-clean
187+
@echo "Building wheel and sdist for v$(VERSION)..."
188+
python3 -m pip install --quiet build
189+
python3 -m build
190+
@echo ""
191+
@echo "Verifying wheel installs correctly..."
192+
@python3 -m pip install --quiet --force-reinstall dist/*.whl
193+
@policy-audit --version
194+
@echo ""
195+
@echo "Artifacts:"
196+
@ls -lh dist/
197+
198+
dist-clean:
199+
@rm -rf dist/ build/ src/*.egg-info
200+
@echo "Cleaned dist/, build/, *.egg-info"
201+
202+
airgap: dist
203+
@echo ""
204+
@echo "Building airgap bundles for Python $(AIRGAP_PYTHON)..."
205+
@chmod +x scripts/build-airgap.sh
206+
scripts/build-airgap.sh --python $(AIRGAP_PYTHON)
207+
208+
release: dist airgap
209+
@echo ""
210+
@echo "=== Creating GitHub Release v$(VERSION) ==="
211+
@if ! command -v gh &>/dev/null || ! gh auth status &>/dev/null; then \
212+
echo ""; \
213+
echo "gh CLI is not available or not authenticated."; \
214+
echo "To publish this release manually:"; \
215+
echo ""; \
216+
echo "1. Tag the release:"; \
217+
echo ""; \
218+
echo " git tag v$(VERSION)"; \
219+
echo " git push origin v$(VERSION)"; \
220+
echo ""; \
221+
echo "2. Go to: https://github.com/cs-shadowbq/falcon-policy-scoring/releases/new"; \
222+
echo ""; \
223+
echo "3. Select tag: v$(VERSION)"; \
224+
echo " Title: falcon-policy-scoring v$(VERSION)"; \
225+
echo " Description: Click 'Generate release notes' for changelog"; \
226+
echo ""; \
227+
echo "4. Attach these files from dist/:"; \
228+
echo ""; \
229+
ls dist/*.whl dist/*.tar.gz dist/SHA256SUMS 2>/dev/null | sort -u | sed 's/^/ /'; \
230+
echo ""; \
231+
echo "5. Verify checksums match dist/SHA256SUMS after upload."; \
232+
echo ""; \
233+
else \
234+
echo ""; \
235+
echo "Release artifacts:"; \
236+
ls dist/*.whl dist/*.tar.gz dist/*-airgap-*.tar.gz dist/SHA256SUMS 2>/dev/null; \
237+
echo ""; \
238+
echo "Creating release..."; \
239+
gh release create "v$(VERSION)" \
240+
--title "falcon-policy-scoring v$(VERSION)" \
241+
--generate-notes \
242+
--notes-start-tag "$$(git tag --sort=-v:refname | sed -n '2p')" \
243+
dist/*.whl \
244+
dist/*.tar.gz \
245+
dist/*-airgap-*.tar.gz \
246+
dist/SHA256SUMS; \
247+
echo ""; \
248+
echo "Release published: https://github.com/cs-shadowbq/falcon-policy-scoring/releases/tag/v$(VERSION)"; \
249+
fi
171250

172251
run-daemon:
173252
python bin/policy-audit daemon --config config/config.yaml --output-dir ./output --verbose

pyproject.toml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "falcon-policy-scoring"
7-
version = "1.8.0"
7+
version = "1.8.1"
88
description = "CrowdStrike Falcon policy analysis and grading tool"
99
readme = "README.md"
1010
license = { file = "LICENSE.md" }
@@ -14,7 +14,7 @@ maintainers = [
1414
{ name = "Scott MacGregor", email = "scott.macgregor@crowdstrike.com" },
1515
]
1616
dependencies = [
17-
"crowdstrike-falconpy>=1.5.4",
17+
"crowdstrike-falconpy>=1.6.3",
1818
"tinydb>=4.8.0",
1919
"schedule>=1.2.2",
2020
"pyyaml>=6.0.3",
@@ -27,14 +27,18 @@ dependencies = [
2727
dev = ["packaging>=25.0", "rich>=14.2.0"]
2828
dynamodb = ["boto3>=1.34.0"]
2929
test = [
30-
"pytest>=9.0.2",
31-
"pytest-cov>=7.0.0",
30+
"pytest>=9.0.2; python_version >= '3.10'",
31+
"pytest>=8.0.0; python_version < '3.10'",
32+
"pytest-cov>=7.0.0; python_version >= '3.10'",
33+
"pytest-cov>=5.0.0; python_version < '3.10'",
3234
"pytest-vcr>=1.0.2",
3335
"freezegun>=1.5.5",
34-
"vcrpy>=8.1.1",
35-
"jsonschema>=4.26.0",
36+
"vcrpy>=8.1.1; python_version >= '3.10'",
37+
"vcrpy>=6.0.0; python_version < '3.10'",
38+
"jsonschema>=4.20.0",
3639
"boto3>=1.34.0",
37-
"moto[dynamodb]>=5.0.0",
40+
"moto[dynamodb]>=5.0.0; python_version >= '3.10'",
41+
"moto[dynamodb]>=4.2.0; python_version < '3.10'",
3842
]
3943
docs = ["sphinx>=8.2.3", "sphinx-autodoc-typehints>=3.2.0"]
4044

0 commit comments

Comments
 (0)