Verifying Releases
Headlamp releases are signed, so you can check that what you downloaded was built by the Headlamp project and hasn't been tampered with.
Release checksums, container images, and Helm charts are signed with Sigstore keyless signing in the GitHub Actions workflows that build them, so there is no long-lived private key that could leak. Release tags are signed by the maintainer who creates the release, with their own key. The Helm chart is also signed with GPG.
Desktop app and Helm chart releases also include SLSA provenance, which records the GitHub Actions workflow, branch or tag, and commit that built them. Provenance is also stored in GitHub's attestation API, so it can be checked with the GitHub CLI.
Signatures for release checksums, container images, and release tags start with
the first release after v0.45.0. For v0.45.0 and earlier, checksums.txt is not
signed, so it only protects against corrupted downloads, not tampered ones.
Provenance for desktop app and Helm chart releases starts with the first release
after v0.46.0.
The cosign commands on this page need cosign v2.6.3 or later, because older versions cannot read the signature format that Headlamp releases use.
Desktop apps and binaries
Each GitHub release includes:
checksums.txt: the SHA-256 checksums of the release's apps and binaries.checksums.txt.sigstore.json: a Sigstore signature bundle forchecksums.txt.headlamp-X.Y.Z.intoto.jsonl: SLSA provenance for the files listed inchecksums.txt.
To verify a download, first verify checksums.txt. It is signed by the release
assets workflow running from the main branch:
cosign verify-blob checksums.txt \
--bundle checksums.txt.sigstore.json \
--certificate-identity 'https://github.com/kubernetes-sigs/headlamp/.github/workflows/push-release-assets.yml@refs/heads/main' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
Then check the files you downloaded against it:
sha256sum --check --ignore-missing checksums.txt
On macOS, use shasum -a 256 --check --ignore-missing checksums.txt. On
Windows, use PowerShell (replace the file name with the one you downloaded); it
prints True if the checksum matches:
$file = 'Headlamp-X.Y.Z-win-x64.exe'
$expected = (Select-String -Path checksums.txt -Pattern " $file`$").Line.Split(' ')[0]
(Get-FileHash -Algorithm SHA256 $file).Hash -eq $expected
The macOS app is also signed and notarized by Apple, so macOS verifies it at
install time. The Windows installers are not yet Authenticode signed, so verify
them with checksums.txt as described above.
To check the provenance of a download, which was generated by the app build workflows:
gh attestation verify Headlamp-X.Y.Z-linux-x64.AppImage \
--repo kubernetes-sigs/headlamp \
--bundle headlamp-X.Y.Z.intoto.jsonl \
--cert-identity-regex '^https://github\.com/kubernetes-sigs/headlamp/\.github/workflows/app-artifacts-(linux|mac|win)\.yml@'
The output shows the workflow and the branch or tag that it built. Without
--bundle, gh fetches the provenance from GitHub instead.
Container images
Release images at ghcr.io/headlamp-k8s/headlamp are signed when they are built
from a release tag, and come with build provenance attestations:
cosign verify ghcr.io/headlamp-k8s/headlamp:vX.Y.Z \
--certificate-identity-regexp '^https://github\.com/kubernetes-sigs/headlamp/\.github/workflows/container-publish\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
The nightly image is signed by scheduled builds from main or manual builds
from a selected branch. Both publish to the same nightly tag. To verify an
image built from main:
cosign verify ghcr.io/headlamp-k8s/headlamp:nightly \
--certificate-identity 'https://github.com/kubernetes-sigs/headlamp/.github/workflows/nightly-build.yml@refs/heads/main' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
For a manual build from another branch, replace refs/heads/main in the
certificate identity above with refs/heads/<selected-branch>.
Helm chart
Each chart release on GitHub (headlamp-helm-X.Y.Z) includes the chart package,
headlamp-X.Y.Z.tgz, a Sigstore signature bundle for it,
headlamp-X.Y.Z.tgz.sigstore.json, SLSA provenance for it,
headlamp-X.Y.Z.tgz.intoto.jsonl, and a GPG .prov provenance file.
Sigstore signatures and SLSA provenance for the chart start with the first chart release after 0.46.0.
To verify the chart with cosign, download the chart and its signature bundle,
then check that it was signed by the chart release workflow running from the
main branch:
helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
helm pull headlamp/headlamp --version X.Y.Z
curl -LO https://github.com/kubernetes-sigs/headlamp/releases/download/headlamp-helm-X.Y.Z/headlamp-X.Y.Z.tgz.sigstore.json
cosign verify-blob headlamp-X.Y.Z.tgz \
--bundle headlamp-X.Y.Z.tgz.sigstore.json \
--certificate-identity 'https://github.com/kubernetes-sigs/headlamp/.github/workflows/helm-chart-release.yml@refs/heads/main' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
To check the chart's provenance, which was generated by the same workflow:
gh attestation verify headlamp-X.Y.Z.tgz \
--repo kubernetes-sigs/headlamp \
--cert-identity 'https://github.com/kubernetes-sigs/headlamp/.github/workflows/helm-chart-release.yml@refs/heads/main'
The GPG signature (key fingerprint
2956 B7F7 1677 6937 0C93 730C 7264 DA7B 85D0 8A37) can be verified with Helm:
The public key is not currently available from public keyservers (see
#5093), so the
gpg --recv-keys command below fails until it is published.
gpg --keyserver hkps://keys.openpgp.org --recv-keys 2956B7F7167769370C93730C7264DA7B85D08A37
gpg --export 2956B7F7167769370C93730C7264DA7B85D08A37 > headlamp-pubring.gpg
helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
helm pull headlamp/headlamp --verify --keyring headlamp-pubring.gpg
Source code
Release tags are signed by the maintainer who creates the release. To check a tag, open it on GitHub and look for the Verified label, which means GitHub has matched the signature to a key registered on the maintainer's GitHub account.
To check a tag locally with git tag -v, first get the public key of the
maintainer who created it (shown as the tagger by git show vX.Y.Z; replace
USERNAME and EMAIL below with their GitHub username and tagger email).
For SSH-signed tags:
curl -s https://api.github.com/users/USERNAME/ssh_signing_keys \
| jq -r '.[].key' | sed 's/^/EMAIL /' > allowed_signers
git -c gpg.ssh.allowedSignersFile=allowed_signers tag -v vX.Y.Z
For GPG-signed tags:
curl -s https://github.com/USERNAME.gpg | gpg --import
git tag -v vX.Y.Z