name: Smoke-test veilor-os OCI # Pulls git.s8n.ru/veilor-org/veilor-os:43 and asserts that the image # contains the veilor brand + the v0.5.x hardening overlay + the v0.7 # CLI tools, and that cosign verifies it against bluebuild/cosign.pub. on: workflow_run: workflows: ["Build veilor-os OCI (BlueBuild)"] types: [completed] workflow_dispatch: permissions: contents: read jobs: smoke: name: OCI smoke test runs-on: nullstone if: >- github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') timeout-minutes: 20 env: IMAGE: git.s8n.ru/veilor-org/veilor-os:43 steps: - name: Checkout uses: actions/checkout@v4.1.7 - name: Fix sudo perms run: chown -R 0:0 /etc/sudo.conf /etc/sudoers /etc/sudoers.d 2>/dev/null || true - name: Install podman + cosign run: | set -euxo pipefail command -v podman >/dev/null || dnf -y install --skip-unavailable podman if ! command -v cosign >/dev/null 2>&1; then curl -fsSL "https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64" \ -o /usr/local/bin/cosign chmod +x /usr/local/bin/cosign fi podman --version cosign version - name: Login + pull OCI image env: FORGEJO_REGISTRY_TOKEN: ${{ secrets.FORGEJO_REGISTRY_TOKEN }} FORGEJO_REGISTRY_USER: ${{ secrets.FORGEJO_REGISTRY_USER }} run: | set -euxo pipefail if [ -n "${FORGEJO_REGISTRY_TOKEN:-}" ]; then echo "$FORGEJO_REGISTRY_TOKEN" | podman login \ --username "${FORGEJO_REGISTRY_USER:-veilor-org}" \ --password-stdin git.s8n.ru fi podman pull "${IMAGE}" - name: Verify cosign signature run: | set -euo pipefail [ -f bluebuild/cosign.pub ] || { echo "[ERR] bluebuild/cosign.pub missing"; exit 1; } cosign verify --key bluebuild/cosign.pub "${IMAGE}" 2>&1 | tail -10 - name: Run OCI assertions run: | set -uo pipefail PASS=0; FAIL=0; ERRORS="" pass() { echo "[PASS] $1"; PASS=$((PASS+1)); } fail() { echo "[FAIL] $1"; FAIL=$((FAIL+1)); ERRORS="${ERRORS} - $1\n"; } img() { podman run --rm "${IMAGE}" /bin/bash -c "$1" 2>/dev/null; } OS=$(img 'cat /etc/os-release 2>/dev/null') echo "$OS" | grep -q 'ID=veilor' && pass "ID=veilor" || fail "ID=veilor missing" echo "$OS" | grep -q 'NAME="veilor-os"' && pass 'NAME="veilor-os"' || fail 'NAME="veilor-os" missing' img 'which sudo' >/dev/null && pass "sudo present" || fail "sudo missing" img 'rpm -q mullvad-browser' >/dev/null && pass "mullvad-browser present" || fail "mullvad-browser missing" img 'rpm -q tailscale' >/dev/null && pass "tailscale present" || fail "tailscale missing" img 'rpm -q yggdrasil' >/dev/null && pass "yggdrasil present" || fail "yggdrasil missing" if img 'grep -qi "^SELINUX=enforcing" /etc/selinux/config'; then pass "SELinux config = enforcing" else fail "SELinux not enforcing" fi img 'test -e /etc/systemd/system/multi-user.target.wants/veilor-firstboot.service \ -o -e /etc/systemd/system/graphical.target.wants/veilor-firstboot.service' >/dev/null \ && pass "veilor-firstboot enabled" || fail "veilor-firstboot not enabled" img 'test -e /etc/systemd/system/multi-user.target.wants/veilor-postinstall.service \ -o -e /etc/systemd/system/graphical.target.wants/veilor-postinstall.service' >/dev/null \ && pass "veilor-postinstall enabled" || fail "veilor-postinstall not enabled" for b in veilor-power veilor-update veilor-doctor veilor-postinstall; do img "test -x /usr/local/bin/${b}" >/dev/null \ && pass "${b} executable" || fail "${b} missing" done if img 'ls /usr/share/veilor-os/scripts/ 2>/dev/null' | grep -qE '(10-harden|20-harden|30-apply)'; then pass "/usr/share/veilor-os/scripts populated" else fail "/usr/share/veilor-os/scripts missing" fi LEAKS=$(img "grep -rIni 'onyx\|192\.168\.0\.\|fedora\.local\|xynki\.dev' /etc/veilor* /usr/share/veilor-os 2>/dev/null") if [ -z "$LEAKS" ]; then pass "no brand leaks" else fail "brand leaks found" echo "$LEAKS" fi echo echo "═══ ${PASS} passed, ${FAIL} failed ═══" if [ "$FAIL" -gt 0 ]; then printf "%b" "$ERRORS" exit 1 fi echo "✓ veilor-os:43 smoke test passed"