This Blastwall proof was recorded in Calabi, my nested-KVM lab for modeling disconnected OpenShift and support-service boundaries in a controlled environment. Calabi gives this run a real IdM server, bastion host, mirror registry, Kerberos flow, and managed endpoint; Blastwall itself does not require Calabi.
What This Proves
This demo shows the whole control path without requiring AAP. AAP is not needed to prove the local behavior: the same IdM state AAP would consume is visible before the mutation step, and the final denial is enforced by the target host SELinux policy.
The run starts from bastion-01, uses eigenstate.ipa to read IdM state before enforcement, deploys policy to mirror-registry, runs AF_ALG, BPF, packet_socket, userns, and io_uring probes as the mapped automation identity, then proves self-protection by blocking sudo-expanded policy manipulation.
The observable flow is:
bastion-01runs the Calabi PoC playbooks locally.eigenstate.ipavalidates the IdM SELinux user map, HBAC rule, sudo rule, and candidate host view.mirror-registryreceives the Blastwall policy RPM.- The automation identity logs in with the expected SELinux context.
- The AF_ALG/authencesn, BPF, packet_socket, userns, io_uring, xfrm, and RxRPC probes are blocked for that mapped automation session.
- The target audit log shows denied
socket,bpf, and namespace syscall evidence forblastwall_t; theio_uringdenial is visible in the probe output. - A temporary sudo expansion exposes
/usr/sbin/semodule, and SELinux still prevents the automation identity from removing a deny module.
What This Does Not Prove
- It does not compete with the AAP demo as the main operator-facing proof. This is the bootstrap and host-local proof.
- It does not require AAP to prove the local behavior. AAP later consumes and records the state shown here.
- It does not run live exploit payloads. The probes exercise safe entry points that should be denied before useful exploit behavior.
Ansible Demo
Evidence Map
- The IdM side is not assumed. It is queried before the endpoint enforcement play runs.
- The inventory candidate view includes
mirror-registry.workshop.lanthrough the Blastwall policy objects. - The target host can install or refresh the Blastwall SELinux policy RPM through an ordinary Ansible workflow.
- The mapped automation session reports
blastwall_u:blastwall_r:blastwall_t:s0. - The AF_ALG/authencesn probe reports
BLOCKED. - The BPF probe reports
BLOCKEDfor bothBPF_MAP_CREATEandBPF_PROG_LOAD. - The packet_socket probe reports
BLOCKEDfor AF_PACKET socket creation. - The userns probe reports
BLOCKEDforunshare(CLONE_NEWUSER). - The io_uring probe reports
BLOCKEDforio_uring_setup, orSKIPon kernels without that object class. - The Dirty Frag probe reports
BLOCKEDforNETLINK_XFRMandAF_RXRPCsocket creation. - The self-protection play shows sudo can be expanded while SELinux still denies
semoduleexecution fromblastwall_t. - A conventional audit-log check shows the SELinux denial evidence from the target host.
Recording Guide
1. Start from the bastion-local PoC tree
pwd
cd ~/blastwall/poc-calabi
Execution starts from the staged repository on bastion-01. That keeps the boundary honest: the workstation is not directly driving guest configuration.
2. Create and prove the IdM identity boundary
ansible-playbook 10-configure-idm.yml
kinit admin
ipa user-show svc-ansible-runner --all --raw | grep -E 'uid:|memberof_group:|memberOf:'
ipa group-show blastwall --all --raw | grep -E 'cn:|member_user:|member:'
The service identity, the blastwall group, and membership are visible before the enforcement play touches mirror-registry.
3. Run the read-side IdM gate
ansible-playbook 15-validate-idm-with-eigenstate.yml | tee /tmp/blastwall-eigenstate.log
eigenstate.ipa reads the SELinux map, HBAC rule, sudo rule, and inventory candidate view before the enforcement play touches mirror-registry.
hbac_rule: blastwall-ssh
selinux_map: blastwall-root-local-map
sudo_rule: blastwall-root-local-sudo
target: mirror-registry.workshop.lan
4. Deploy policy and run the playbook proof
ansible-playbook 30-deploy-and-test.yml | tee /tmp/blastwall-proof.log
The target host installs the Blastwall RPM, refreshes local policy state, and runs the automated validation for AF_ALG, BPF, packet_socket, userns, io_uring, xfrm, and RxRPC.
5. Mark the Dirty Frag response date
date -u '+Dirty Frag response marker: %Y-%m-%d %H:%M:%S UTC'
echo 'Blastwall 0.5.2: verify xfrm and RxRPC are denied for confined automation'
This callout keeps the timing visible in the non-AAP proof: Dirty Frag was publicly documented on May 7, 2026, and this run verifies the xfrm and RxRPC deny scopes on May 8, 2026.
6. Inspect and run the probes directly
kinit svc-ansible-runner
ssh -o GSSAPIAuthentication=yes \
svc-ansible-runner@mirror-registry.workshop.lan \
/usr/local/libexec/blastwall-poc/trigger-copyfail-afalg.py
ssh -o GSSAPIAuthentication=yes \
svc-ansible-runner@mirror-registry.workshop.lan \
/usr/local/libexec/blastwall-poc/trigger-bpf-deny.py
ssh -o GSSAPIAuthentication=yes \
svc-ansible-runner@mirror-registry.workshop.lan \
/usr/local/libexec/blastwall-poc/trigger-packet-socket-deny.py
ssh -o GSSAPIAuthentication=yes \
svc-ansible-runner@mirror-registry.workshop.lan \
/usr/local/libexec/blastwall-poc/trigger-userns-deny.py
ssh -o GSSAPIAuthentication=yes \
svc-ansible-runner@mirror-registry.workshop.lan \
/usr/local/libexec/blastwall-poc/trigger-io-uring-deny.py
ssh -o GSSAPIAuthentication=yes \
svc-ansible-runner@mirror-registry.workshop.lan \
/usr/local/libexec/blastwall-poc/trigger-dirtyfrag-deny.py
The operator inspects the probe source, gets a Kerberos ticket for svc-ansible-runner, and runs the probes over GSSAPI SSH so the denial is visible as normal command output.
blastwall_u:blastwall_r:blastwall_t:s0
BLOCKED: AF_ALG socket creation denied with errno 13
BLOCKED: bpf(BPF_MAP_CREATE) denied with errno 13
BLOCKED: bpf(BPF_PROG_LOAD) denied with errno 13
BLOCKED: AF_PACKET socket creation denied with errno 13
BLOCKED: unshare(CLONE_NEWUSER) denied with EACCES errno 13
BLOCKED: io_uring_setup denied with EPERM [CVE-2026-43006]
BLOCKED: Dirty Frag NETLINK_XFRM socket creation denied with errno 13
BLOCKED: Dirty Frag AF_RXRPC socket creation denied with errno 13
7. Read the target audit log
ansible automation_endpoints -i inventory.yml -b -m shell -a '
grep -a '\''subj=blastwall'\'' /var/log/audit/audit.log |
tr '\''\035'\'' '\''\n'\'' |
grep -E '\''type=SYSCALL.*(syscall=41|syscall=321|syscall=272).*exit=-13|SYSCALL=(socket|bpf|unshare).*AUID="svc-ansible-runner"'\'' |
sed -E '\''s/.*audit\(([^)]*)\).*syscall=([0-9]+).*exit=(-?[0-9]+).*comm="([^"]+)".*subj=([^ ]+).*/type=SYSCALL audit(\1) syscall=\2 exit=\3 comm="\4" subj=\5/; s/.*SYSCALL=([^ ]+).*AUID="([^"]+)".*/ARCH SYSCALL=\1 AUID="\2"/'\'' |
tail -n 16'
The audit check is intentionally conventional, but it is executed through Ansible against the target endpoint. It is there to show SELinux enforcement from the target host, not just stored Ansible variables.
8. Prove the policy protects itself
ansible-playbook 35-test-self-protection.yml | tee /tmp/blastwall-selfprotect.log
grep -E \
'sudo_expansion_seen|semodule_attempt_rc|semodule_attempt_stderr|Permission denied|blastwall-(alg|bpf|packet|userns|io-uring|xfrm|rxrpc|policy)' \
/tmp/blastwall-selfprotect.log
The self-protection play temporarily adds /usr/sbin/semodule to the Blastwall sudo command group, verifies the automation identity can see that sudo expansion, then attempts to remove a deny module. Sudo is not the final boundary: SELinux denies semodule from blastwall_t, and the deny modules remain installed.
Expected Result
A successful bootstrap proof shows the mapped context blastwall_u:blastwall_r:blastwall_t:s0, sudo UID 0 without leaving that context, blocked AF_ALG, BPF, packet_socket, userns, io_uring, xfrm, and RxRPC probes, audit evidence on the target host, and a self-protection denial when the confined automation identity attempts policy manipulation.
Replay Link
Use Ansible Lab for the task-first replay procedure and compact playbook chain.
Scope Notes
- It does not replace a kernel fix.
- SELinux does not inspect the same kernel hook arguments as BPF LSM.
- It does not require AAP to prove the local behavior.
- It does not run live exploit payloads. The probes exercise safe entry points that should be denied before reaching the dangerous path.
- It does not say host markers are proof by themselves. They are useful only after a local verification workflow writes them.