RACFHound
Automated RACF security analysis for z/OS. Collects the RACF database via SSH, transforms it into a BloodHound-compatible graph, and uploads it to BloodHound CE for attack path analysis.
z/OS (SSH + FTP) Linux BloodHound CE
┌──────────────┐ ┌─────────────────┐ ┌────────────────┐
│ RACF DB │─IRRDBU00→│ racfdump.txt │ │ Graph DB │
│ SYS1.RACFDS │ │ apflist.txt │─────→ │ RACF nodes │
│ APF/PARMLIB │ │ opengraph.json │ │ Attack paths │
└──────────────┘ └─────────────────┘ └────────────────┘
Quick start — collect from z/OS
pip install racfhound
# 1. Collect from z/OS
racfhound collect \
--host zos.example.com --user IBMUSER --key ~/.ssh/id_rsa
# 2. Transform to BloodHound graph
racfhound export --dump collect_output/racfdump.txt \
--apf collect_output/apflist.txt \
--parmlib collect_output/parmlist.txt \
--proclib collect_output/proclist.txt
# 3. Authenticate to BloodHound
export BH_URL=http://bloodhound:8080
export BH_TOKEN=$(racfhound login --user admin@example.com --password 's3cr3t')
# 4. Provision BloodHound (once per instance)
racfhound provision
racfhound queries
# 5. Upload graph
racfhound upload racf_opengraph.json
Quick start — local IRRDBU00 unload
If you already have an IRRDBU00 unload (from manual FTP, a previous run, or a third-party extraction), skip straight to transform:
# Transform an existing unload — no z/OS connection required
racfhound export --dump /path/to/racfdump.txt
# With optional context lists for APF/PARMLIB/PROCLIB marking
racfhound export --dump /path/to/racfdump.txt \
--apf apflist.txt --parmlib parmlist.txt --proclib proclist.txt
# Then authenticate and upload as normal
export BH_TOKEN=$(racfhound login --user admin@example.com --password 's3cr3t')
racfhound upload racf_opengraph.json
Prerequisites
| Requirement | Notes |
|---|---|
| Python ≥ 3.10 | |
| BloodHound CE | For graph analysis |
| z/OS OpenSSH | SSH + SFTP access — only needed for remote collection |
| z/OS FTP server | For retrieving the RACF dump — only needed for remote collection |
| IRRDBU00 authority | RACF READ on the database dataset — only needed for remote collection |
The collecting user needs:
- SSH login to z/OS UNIX System Services
- READ access to the RACF database dataset (
SYS1.RACFDSor equivalent) - TSO access (for
RVARY LISTand job submission) - FTP access to the z/OS system
Architecture
RACFHound is built from two cooperating packages:
mfpandas-racfhound (transforms IRRDBU00 output → BloodHound OpenGraph)
↑ imported by github.com/JonathanPrince/mfpandas-racfhound
racfhound (collect → transform → export pipeline + CLI)
collect/ SSH collection, JCL submission, FTP retrieval
data/ Bundled custom-types.json + 40 Cypher queries
Both packages depend on mfpandas (upstream IRRDBU00 parser by @wizardofzos).
The transformation is done by mfpandas-racfhound which maps RACF profiles, ACLs, group structure, and system attributes into BloodHound graph nodes and edges.
Commands
| Command | Description |
|---|---|
collect |
Collect from z/OS via SSH/FTP — RVARY LIST, IRRDBU00, PARMLIB |
export |
Transform a RACF unload file into BloodHound OpenGraph JSON |
login |
Authenticate to BloodHound CE and print a session token |
provision |
Register RACF node type icons and colours (once per instance) |
queries |
Load 40 bundled RACF Cypher queries (once per instance) |
upload |
Upload an OpenGraph JSON file to BloodHound CE |
What gets collected
| Artifact | Source | Purpose |
|---|---|---|
racfdump.txt |
IRRDBU00 unload | All RACF profiles (users, groups, datasets, resources) |
apflist.txt |
PARMLIB PROGxx | Marks APF-authorised libraries in the graph |
parmlist.txt |
PARMLIB member | Marks PARMLIB datasets in the graph |
proclist.txt |
PARMLIB member | Marks PROCLIB datasets in the graph |
Environment variables
| Variable | Command | Description |
|---|---|---|
MF_HOST |
collect | z/OS SSH hostname |
MF_PORT |
collect | SSH port (default 22) |
MF_FTP_PORT |
collect | FTP port (default 21) |
MF_USER |
collect | TSO/USS username |
MF_KEY |
collect | SSH private key path |
MF_PASSWORD |
collect | SSH/FTP password |
MF_RACF_DSN |
collect | RACF database DSN (overrides RVARY LIST) |
MF_JOB_CLASS |
collect | JES job class |
MF_MSG_CLASS |
collect | JES message class |
BH_URL |
login / provision / queries / upload | BloodHound base URL |
BH_USER |
login | BloodHound username / email |
BH_PASSWORD |
login | BloodHound password |
BH_TOKEN |
provision / queries / upload | BloodHound JWT session token |
Documentation
Graph model
Nodes: RACFUser · RACFGroup · RACFDataset · RACFResource · RACFPrivilege · RACFStartedTask · RACFClass · RACFCertificate · RACFMFAFactor · RACFUndefined
Edges: RACFMemberOf · RACFHasSubgroup · RACFGroupAuth_{USE|CREATE|CONNECT|JOIN} · RACFOwns · RACFCanRead · RACFCanWrite · RACFCanExecute · RACFHasPrivilege · RACFSurrogateFor · RACFStartedTaskRunsAs · RACFCertificateFor · RACFPassticketFor · RACFCanAccessKey
See the query reference and BloodHound setup for more detail.
Metadata
Release files for racfhound 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| racfhound-0.1.1.tar.gz | 21.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| racfhound-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.6 kB
Release files / racfhound-0.1.1.tar.gz
| Download URL | racfhound-0.1.1.tar.gz |
|---|---|
| Size | 21.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fc5f41e0d1e090c5ccdaeeb941a55b756d130134b99e26cc393174720c4806a5
|
|
BLAKE2b-256 checksum How to use checksums |
15668f5bddd5fb66c668c93814796b421d3e16b15ba4aabc3eeb3e5154132352
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.2
|
Release files / racfhound-0.1.1-py3-none-any.whl
| Download URL | racfhound-0.1.1-py3-none-any.whl |
|---|---|
| Size | 39.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
274a04fc0e7cefeb48488ff4e59fb74871c4c470241003a4a9767350f2e07735
|
|
BLAKE2b-256 checksum How to use checksums |
a1045fbae95901437c6302904be3bce3de2fe7d564a3e5ce1614ac4c2190da24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.2
|