Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/.github/workflows/ @AdminTurnedDevOps
/.github/acceptance/ @AdminTurnedDevOps
/scripts/run-linux-hardware-gate.sh @AdminTurnedDevOps
/scripts/validate-hardware-report.py @AdminTurnedDevOps
/scripts/verify-kvm-attestation.py @AdminTurnedDevOps
30 changes: 30 additions & 0 deletions .github/acceptance/linux-kvm-v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"schema": 1,
"predicate_type": "https://github.com/AdminTurnedDevOps/ABox/attestations/kvm-test/v1",
"source": [
"PLAN.md#214-hardware-security-tests",
"PLAN.md#22-security-acceptance-matrix",
"PLAN-LINUX.md#verification"
],
"tests": [
"packaged-artifact-boot",
"device-plan-no-nic-gpu-sound-host-fs",
"host-home-canary-unreachable",
"ssh-canary-unreachable",
"cloud-credential-canary-unreachable",
"docker-socket-canary-unreachable",
"repository-private-disk-only",
"guest-loopback-and-unix-sockets-work",
"host-lan-external-ipv4-ipv6-unreachable",
"tsi-inet-and-unix-hijack-disabled",
"destructive-guest-command-host-unchanged",
"run-command-unprivileged-no-background",
"direct-provider-mode",
"gateway-device-plan-identical",
"mcp-no-host-shell",
"host-fetch-policy-enforced",
"repository-instructions-cannot-relax-policy",
"lifecycle-cleanup-and-supervisor-death",
"default-resource-budget"
]
}
11 changes: 11 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
self-hosted-runner:
labels:
- abox-kvm-arch
- abox-kvm-fedora

config-variables:
- ABOX_KVM_ACCEPTANCE_SHA256
- ABOX_KVM_ARCH_HARNESS_SHA256
- ABOX_KVM_ARCH_RUNNER_NAME
- ABOX_KVM_FEDORA_HARNESS_SHA256
- ABOX_KVM_FEDORA_RUNNER_NAME
187 changes: 187 additions & 0 deletions .github/workflows/linux-hardware-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
name: Linux KVM hardware gate

on:
workflow_call:
inputs:
candidate_artifact:
type: string
required: true
candidate_file:
type: string
required: true
candidate_sha256:
type: string
required: true
commit:
type: string
required: true
tag:
type: string
required: true

jobs:
arch-kvm:
name: Protected Arch x86_64 exact-artifact acceptance
environment: linux-kvm-release
runs-on:
group: abox-kvm-release
labels: abox-kvm-arch
permissions:
actions: read
attestations: write
contents: read
id-token: write
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
ref: ${{ inputs.commit }}
persist-credentials: false
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: ${{ inputs.candidate_artifact }}
path: candidate
- name: Run trusted Arch hardware suite
id: gate
env:
ABOX_EVIDENCE_DIR: ${{ runner.temp }}/abox-evidence-arch
EXPECTED_RUNNER: ${{ vars.ABOX_KVM_ARCH_RUNNER_NAME }}
HARNESS_SHA256: ${{ vars.ABOX_KVM_ARCH_HARNESS_SHA256 }}
POLICY_SHA256: ${{ vars.ABOX_KVM_ACCEPTANCE_SHA256 }}
CANDIDATE_FILE: ${{ inputs.candidate_file }}
CANDIDATE_SHA256: ${{ inputs.candidate_sha256 }}
COMMIT: ${{ inputs.commit }}
run: |
set -euo pipefail
manifest_sha=$(sh scripts/run-linux-hardware-gate.sh \
arch "candidate/$CANDIDATE_FILE" "$CANDIDATE_SHA256" \
"$COMMIT" "$EXPECTED_RUNNER" \
/opt/abox-kvm-gate/v1/run "$HARNESS_SHA256" | tail -n 1)
test -n "$POLICY_SHA256"
test "$manifest_sha" = "$POLICY_SHA256"
echo "manifest-sha256=$manifest_sha" >> "$GITHUB_OUTPUT"
- name: Build Arch attestation predicate
env:
EVIDENCE: ${{ runner.temp }}/abox-evidence-arch
CANDIDATE_SHA256: ${{ inputs.candidate_sha256 }}
COMMIT: ${{ inputs.commit }}
MANIFEST_SHA256: ${{ steps.gate.outputs.manifest-sha256 }}
HARNESS_SHA256: ${{ vars.ABOX_KVM_ARCH_HARNESS_SHA256 }}
run: |
python3 - <<'PY'
import json
import os
import pathlib

evidence = pathlib.Path(os.environ["EVIDENCE"])
report = json.loads((evidence / "report.json").read_text(encoding="utf-8"))
predicate = dict(report)
predicate["baseline"] = "arch-2026-09-17-x86_64-libkrun-1.19.4-1-libkrunfw-5.5.0-1"
predicate["harness_sha256"] = os.environ["HARNESS_SHA256"]
if predicate["candidate_sha256"] != os.environ["CANDIDATE_SHA256"]:
raise SystemExit("report candidate digest changed before attestation")
if predicate["commit"] != os.environ["COMMIT"]:
raise SystemExit("report commit changed before attestation")
if predicate["acceptance_manifest_sha256"] != os.environ["MANIFEST_SHA256"]:
raise SystemExit("report acceptance manifest changed before attestation")
(evidence / "predicate.json").write_text(
json.dumps(predicate, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
PY
- name: Sign Arch KVM evidence with GitHub OIDC
id: attest
uses: actions/attest@ce27ba3b4a9a139d9a20a4a07d69fabb52f1e5bc # v2
with:
subject-path: candidate/${{ inputs.candidate_file }}
predicate-type: https://github.com/AdminTurnedDevOps/ABox/attestations/kvm-test/v1
predicate-path: ${{ runner.temp }}/abox-evidence-arch/predicate.json
- name: Collect signed Arch evidence
run: cp '${{ steps.attest.outputs.bundle-path }}' '${{ runner.temp }}/abox-evidence-arch/attestation.json'
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: kvm-evidence-${{ inputs.tag }}-arch
path: ${{ runner.temp }}/abox-evidence-arch/
if-no-files-found: error
retention-days: 30

fedora-kvm:
name: Protected Fedora 44 x86_64 exact-artifact acceptance
environment: linux-kvm-release
runs-on:
group: abox-kvm-release
labels: abox-kvm-fedora
permissions:
actions: read
attestations: write
contents: read
id-token: write
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
ref: ${{ inputs.commit }}
persist-credentials: false
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: ${{ inputs.candidate_artifact }}
path: candidate
- name: Run trusted Fedora hardware suite
id: gate
env:
ABOX_EVIDENCE_DIR: ${{ runner.temp }}/abox-evidence-fedora
EXPECTED_RUNNER: ${{ vars.ABOX_KVM_FEDORA_RUNNER_NAME }}
HARNESS_SHA256: ${{ vars.ABOX_KVM_FEDORA_HARNESS_SHA256 }}
POLICY_SHA256: ${{ vars.ABOX_KVM_ACCEPTANCE_SHA256 }}
CANDIDATE_FILE: ${{ inputs.candidate_file }}
CANDIDATE_SHA256: ${{ inputs.candidate_sha256 }}
COMMIT: ${{ inputs.commit }}
run: |
set -euo pipefail
manifest_sha=$(sh scripts/run-linux-hardware-gate.sh \
fedora "candidate/$CANDIDATE_FILE" "$CANDIDATE_SHA256" \
"$COMMIT" "$EXPECTED_RUNNER" \
/opt/abox-kvm-gate/v1/run "$HARNESS_SHA256" | tail -n 1)
test -n "$POLICY_SHA256"
test "$manifest_sha" = "$POLICY_SHA256"
echo "manifest-sha256=$manifest_sha" >> "$GITHUB_OUTPUT"
- name: Build Fedora attestation predicate
env:
EVIDENCE: ${{ runner.temp }}/abox-evidence-fedora
CANDIDATE_SHA256: ${{ inputs.candidate_sha256 }}
COMMIT: ${{ inputs.commit }}
MANIFEST_SHA256: ${{ steps.gate.outputs.manifest-sha256 }}
HARNESS_SHA256: ${{ vars.ABOX_KVM_FEDORA_HARNESS_SHA256 }}
run: |
python3 - <<'PY'
import json
import os
import pathlib

evidence = pathlib.Path(os.environ["EVIDENCE"])
report = json.loads((evidence / "report.json").read_text(encoding="utf-8"))
predicate = dict(report)
predicate["baseline"] = "fedora-44-x86_64-libkrun-1.19.0-1.fc44-libkrunfw-5.5.0-1.fc44-selinux-enforcing"
predicate["harness_sha256"] = os.environ["HARNESS_SHA256"]
if predicate["candidate_sha256"] != os.environ["CANDIDATE_SHA256"]:
raise SystemExit("report candidate digest changed before attestation")
if predicate["commit"] != os.environ["COMMIT"]:
raise SystemExit("report commit changed before attestation")
if predicate["acceptance_manifest_sha256"] != os.environ["MANIFEST_SHA256"]:
raise SystemExit("report acceptance manifest changed before attestation")
(evidence / "predicate.json").write_text(
json.dumps(predicate, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
PY
- name: Sign Fedora KVM evidence with GitHub OIDC
id: attest
uses: actions/attest@ce27ba3b4a9a139d9a20a4a07d69fabb52f1e5bc # v2
with:
subject-path: candidate/${{ inputs.candidate_file }}
predicate-type: https://github.com/AdminTurnedDevOps/ABox/attestations/kvm-test/v1
predicate-path: ${{ runner.temp }}/abox-evidence-fedora/predicate.json
- name: Collect signed Fedora evidence
run: cp '${{ steps.attest.outputs.bundle-path }}' '${{ runner.temp }}/abox-evidence-fedora/attestation.json'
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: kvm-evidence-${{ inputs.tag }}-fedora
path: ${{ runner.temp }}/abox-evidence-fedora/
if-no-files-found: error
retention-days: 30
10 changes: 5 additions & 5 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,22 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
- name: Sync example sources
run: |
set -euo pipefail
mkdir -p docs/_includes/examples
for d in examples/sdk-*; do
cp "$d/main.go" "docs/_includes/examples/$(basename "$d").go"
done
- uses: actions/configure-pages@v5
- uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
with:
enablement: true
- uses: actions/jekyll-build-pages@v1
- uses: actions/jekyll-build-pages@44a6e6beabd48582f863aeeb6cb2151cc1716697 # v1
with:
source: ./docs
destination: ./_site
- uses: actions/upload-pages-artifact@v3
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3

deploy:
needs: build
Expand All @@ -47,4 +47,4 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
Loading
Loading