Verifying zone kernel images

5 min read · Intermediate


Why verify zone kernel images?

Every Edera zone runs its own Linux kernel, independent of the host. Platform engineers select which kernel a workload runs by setting a pod annotation:

metadata:
  annotations:
    dev.edera/kernel: ghcr.io/edera-dev/zone-kernel:6.12.69

This means different pods on the same node can run entirely different kernels. The host kernel and the zone kernel are independent—you can see this by comparing uname -a on the host versus inside a zone:

# Host node
Linux ip-192-168-81-255 6.18.16 #1 SMP PREEMPT_DYNAMIC ...

# Inside an Edera zone on the same node
Linux raider-edera 6.12.69 #1 SMP PREEMPT_DYNAMIC ...

The zone kernel is the kernel your workload runs on at ring 0. Your application’s syscalls go directly to it. If an attacker compromises a zone kernel image—through a supply chain attack on the build pipeline, a registry compromise, or a tag substitution—they gain ring 0 execution inside that zone.

Edera’s hypervisor boundary contains the blast radius: a compromised zone kernel cannot escape to the host or other zones. But ring 0 inside the zone means full control over that workload and its data.

Edera recommends verifying zone kernel signatures for all production workloads. This guide covers how to do that manually with Sigstore cosign, and points toward admission-time enforcement with Kyverno.

Prerequisites

Install cosign and crane:

# macOS
brew install sigstore/tap/cosign crane

# Linux (cosign)
go install github.com/sigstore/cosign/v2/cmd/cosign@latest

# Linux (crane)
go install github.com/google/go-containerregistry/cmd/crane@latest

Published kernel images

Edera publishes kernel images to ghcr.io/edera-dev/ with the following naming convention:

ImageDescription
ghcr.io/edera-dev/zone-kernelStandard zone kernel
ghcr.io/edera-dev/host-kernelHost (hypervisor) kernel
ghcr.io/edera-dev/zone-amdgpu-kernelZone kernel with AMD GPU support
ghcr.io/edera-dev/zone-nvidiagpu-kernelZone kernel with NVIDIA GPU support

Each image also has a corresponding -sdk variant (for example, ghcr.io/edera-dev/zone-kernel-sdk).

All images are built and signed by the edera-dev/linux-kernel-oci GitHub Actions pipeline.

Verifying a kernel image

Step 1: Resolve the platform digest

Edera kernel images are published as multi-architecture OCI image indexes. Signatures are attached to the per-platform manifest, not the image index itself. This means you need to resolve the platform-specific digest before verifying.

For linux/amd64:

DIGEST=$(crane manifest ghcr.io/edera-dev/zone-kernel:latest | \
  jq -r '.manifests[] | select(.platform.architecture == "amd64" and .platform.os == "linux") | .digest')

For linux/aarch64:

DIGEST=$(crane manifest ghcr.io/edera-dev/zone-kernel:latest | \
  jq -r '.manifests[] | select(.platform.architecture == "aarch64" and .platform.os == "linux") | .digest')

Step 2: Verify the signature

cosign verify \
  "ghcr.io/edera-dev/zone-kernel@${DIGEST}" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity "https://github.com/edera-dev/linux-kernel-oci/.github/workflows/matrix.yml@refs/heads/main" \
  --certificate-github-workflow-repository edera-dev/linux-kernel-oci

A successful verification prints the signature payload and:

The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority certificates

Verifying other images

Replace zone-kernel with any image from the table above. The signing identity and issuer are the same for all images:

# Example: verify the host kernel
DIGEST=$(crane manifest ghcr.io/edera-dev/host-kernel:latest | \
  jq -r '.manifests[] | select(.platform.architecture == "amd64" and .platform.os == "linux") | .digest')

cosign verify \
  "ghcr.io/edera-dev/host-kernel@${DIGEST}" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity "https://github.com/edera-dev/linux-kernel-oci/.github/workflows/matrix.yml@refs/heads/main" \
  --certificate-github-workflow-repository edera-dev/linux-kernel-oci

Verifying a specific version

Replace :latest with the version tag:

DIGEST=$(crane manifest ghcr.io/edera-dev/zone-kernel:6.12.25 | \
  jq -r '.manifests[] | select(.platform.architecture == "amd64" and .platform.os == "linux") | .digest')

cosign verify \
  "ghcr.io/edera-dev/zone-kernel@${DIGEST}" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity "https://github.com/edera-dev/linux-kernel-oci/.github/workflows/matrix.yml@refs/heads/main" \
  --certificate-github-workflow-repository edera-dev/linux-kernel-oci

What the verification proves

Cosign keyless verification with GitHub Actions OIDC confirms:

  1. The image was built by GitHub Actions in the edera-dev/linux-kernel-oci repository (not by a third party or local build).
  2. The build ran on the main branch via the matrix.yml workflow.
  3. The signature is recorded in the Rekor transparency log, providing a tamper-evident audit trail.
ℹ️
Cosign keyless signing does not use a static key pair. Instead, each build receives a short-lived certificate from Sigstore’s Fulcio CA, bound to the GitHub Actions OIDC token. The certificate identity (workflow path + ref) is what you verify against.

Enforcing verification at admission time

Manual verification is useful for auditing, but production clusters should enforce kernel image signatures automatically. Kyverno’s ImageValidatingPolicy can extract the image reference from the dev.edera/kernel annotation and verify its cosign signature before the pod is admitted.

apiVersion: kyverno.io/v2
kind: ImageValidatingPolicy
metadata:
  name: verify-edera-kernel
spec:
  images:
    - name: kernel-image
      expression: '[object.metadata.annotations["dev.edera/kernel"]]'
  validations:
    - attestors:
        - entries:
            - keyless:
                subject: "https://github.com/edera-dev/linux-kernel-oci/.github/workflows/matrix.yml@refs/heads/main"
                issuer: "https://token.actions.githubusercontent.com"
                rekor:
                  url: https://rekor.sigstore.dev
⚠️
This policy is provided as a starting point. At time of writing, Edera kernel image signatures are attached to per-platform manifests rather than the OCI image index. Tag-based verification at admission time may not resolve to the signed digest. Check the linux-kernel-oci repository for updates on image index signing.

Troubleshooting

no signatures found

This usually means you are verifying against the image index (manifest list) digest rather than the per-platform manifest digest. Make sure you resolve the platform digest with crane manifest first, as shown above.

certificate identity mismatch

The signing workflow is .github/workflows/matrix.yml on refs/heads/main. If you see a mismatch, check whether the image was built from a different branch or workflow. Images built from non-main branches are not signed with the main branch identity.

no matching signatures with correct identity

The image tag may have been rebuilt since the signature was created. Verify against a specific version tag or digest rather than :latest.

Last updated on