Skip to content
Open
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
83 changes: 80 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ on:
permissions:
contents: write
packages: write
# Required for keyless cosign signing via GitHub OIDC
id-token: write

env:
GO_VERSION: "1.25"
REGISTRY: ghcr.io
IMAGE: ghcr.io/optiqor/kerno

jobs:
release:
Expand Down Expand Up @@ -50,14 +54,77 @@ jobs:
- name: Set up QEMU (multi-arch)
uses: docker/setup-qemu-action@v4

- name: Install cosign
uses: sigstore/cosign-installer@v3
with:
cosign-release: "v2.2.4"

- name: Install Syft
uses: anchore/sbom-action/download-syft@v0

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
id: goreleaser
uses: goreleaser/goreleaser-action@v2
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Extract image digest (versioned tag)
id: digest-tag
run: |
TAG="${{ github.ref_name }}"
DIGEST=$(docker buildx imagetools inspect "${{ env.IMAGE }}:${TAG}" \
--format '{{json .Manifest}}' | jq -r '.digest')
echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"

- name: Sign container image (versioned tag)
env:
COSIGN_EXPERIMENTAL: "1"
run: |
cosign sign --yes \
"${{ env.IMAGE }}:${{ steps.digest-tag.outputs.tag }}@${{ steps.digest-tag.outputs.digest }}"

- name: Extract image digest (latest tag)
id: digest-latest
run: |
DIGEST=$(docker buildx imagetools inspect "${{ env.IMAGE }}:latest" \
--format '{{json .Manifest}}' | jq -r '.digest')
echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT"

- name: Sign container image (latest tag)
env:
COSIGN_EXPERIMENTAL: "1"
run: |
cosign sign --yes \
"${{ env.IMAGE }}:latest@${{ steps.digest-latest.outputs.digest }}"

- name: Generate SBOM (container image)
uses: anchore/sbom-action@v0
with:
image: "${{ env.IMAGE }}:${{ steps.digest-tag.outputs.tag }}"
format: cyclonedx-json
output-file: "${{ github.workspace }}/kerno_${{ steps.digest-tag.outputs.tag }}_sbom.cyclonedx.json"
artifact-name: "kerno_${{ steps.digest-tag.outputs.tag }}_sbom.cyclonedx.json"

- name: Attest SBOM to image (versioned tag)
env:
COSIGN_EXPERIMENTAL: "1"
run: |
cosign attest --yes \
--predicate "${{ github.workspace }}/kerno_${{ steps.digest-tag.outputs.tag }}_sbom.cyclonedx.json" \
--type cyclonedx \
"${{ env.IMAGE }}:${{ steps.digest-tag.outputs.tag }}@${{ steps.digest-tag.outputs.digest }}"

- name: Upload SBOM to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: "${{ github.workspace }}/kerno_${{ steps.digest-tag.outputs.tag }}_sbom.cyclonedx.json"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

snapshot:
name: Snapshot build (PR)
Expand All @@ -79,13 +146,23 @@ jobs:
sudo apt-get install -y --no-install-recommends \
clang llvm libbpf-dev linux-headers-generic

- name: Install cosign
uses: sigstore/cosign-installer@v3
with:
cosign-release: "v2.2.4"

- name: Install Syft
uses: anchore/sbom-action/download-syft@v0

- name: Run GoReleaser snapshot
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v2
with:
distribution: goreleaser
version: "~> v2"
args: release --snapshot --clean
args: release --snapshot --clean --skip=sign
env:
COSIGN_EXPERIMENTAL: ""
GORELEASER_SKIP: sign
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload snapshot packages
Expand Down
31 changes: 26 additions & 5 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Copyright 2026 Optiqor contributors
# SPDX-License-Identifier: Apache-2.0
# https://goreleaser.com/customization/

version: 2

Expand All @@ -9,9 +8,6 @@ project_name: kerno
before:
hooks:
- go mod tidy
# Generate bpf2go bindings (*_bpfel.go) and rewrite their build tag
# so the `ebpf` tag selects them over the no-clang stubs in gen_stub.go.
# The release workflow installs clang + libbpf-dev before invoking goreleaser.
- make generate

builds:
Expand All @@ -27,7 +23,6 @@ builds:
- arm64
flags:
- -trimpath
# `ebpf` tag selects the bpf2go-generated bindings over the no-clang stubs.
tags:
- ebpf
ldflags:
Expand All @@ -50,6 +45,32 @@ archives:
checksum:
name_template: "checksums.txt"

signs:
# skip signing in snapshot/PR builds
- cmd: cosign
signature: "${artifact}.sig"
certificate: "${artifact}.pem"
args:
- sign-blob
- --yes
- --output-signature=${artifact}.sig
- --output-certificate=${artifact}.pem
- "${artifact}"
artifacts: checksum
output: true

sboms:
- id: binary-sbom
artifacts: binary
documents:
- "{{ .ArtifactName }}_sbom.cyclonedx.json"
args:
- "$artifact"
- "--file"
- "$document"
- "--output"
- "cyclonedx-json"

changelog:
sort: asc
use: github
Expand Down
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<div align="center">

# KERNO

Check warning on line 3 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (KERNO)

### The production incident diagnosis engine for Kubernetes

**Your cluster broke. Your dashboards are green. Users are paging.**
**Run `kerno doctor`. 30 seconds. Root cause. Plain English.**

Check warning on line 8 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (kerno)

<sub>Same single binary runs on bare metal, VMs, EC2, GCE - wherever Linux lives.</sub>

Expand All @@ -18,30 +18,30 @@

[**Quick Start**](#quick-start) · [**How It Works**](#how-it-works) · [**Features**](#features) · [**Kubernetes**](#kubernetes-deployment) · [**Docs**](docs/architecture.md)

<img src="demo.gif" alt="kerno doctor demo" width="900" />

Check warning on line 21 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (kerno)

</div>

---

## What is Kerno?

Check warning on line 27 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (Kerno)

Kerno is a **Kubernetes-native incident diagnosis engine** built on eBPF.

Check warning on line 29 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (Kerno)
It runs as a DaemonSet on every node, watches the kernel - not your app - and answers a single question on demand:

> *Why is production broken right now?*

```bash
kubectl -n kerno-system exec ds/kerno -- kerno doctor

Check warning on line 35 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (kerno)

Check warning on line 35 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (kerno)

Check warning on line 35 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (kerno)
```

30 seconds later you get a ranked diagnostic report with **plain-English causes, evidence, ETAs, and copy-paste fix steps** - no dashboards to wire, no query language to learn, no agents in your app.

The kernel knows minutes before your APM. Hours before your users. Kerno makes that visible.

Check warning on line 40 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (Kerno)

**Same binary outside Kubernetes too.** `curl | bash` it onto any bare-metal box, EC2 instance, or systemd VM and `sudo kerno doctor` works exactly the same.

## Why Kerno?

Check warning on line 44 in README.md

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (Kerno)

It's 3am. PagerDuty fires. Latency is up, error budget is burning, and every dashboard you own is **green**.

Expand Down Expand Up @@ -715,6 +715,64 @@

---

## Verifying Release Artifacts

Every Kerno release is signed using [Sigstore](https://docs.sigstore.dev/cosign/signing/overview/) keyless signing — no private key to manage or trust.

### Verify a container image

```bash
cosign verify ghcr.io/optiqor/kerno:v0.1.0 \
--certificate-identity-regexp '^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```

### Verify binary checksums

```bash
VERSION=v0.1.0
BASE=https://github.com/optiqor/kerno/releases/download/${VERSION}

curl -fsSL ${BASE}/checksums.txt -o checksums.txt
curl -fsSL ${BASE}/checksums.txt.sig -o checksums.txt.sig
curl -fsSL ${BASE}/checksums.txt.pem -o checksums.txt.pem

cosign verify-blob checksums.txt \
--signature checksums.txt.sig \
--certificate checksums.txt.pem \
--certificate-identity-regexp '^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com

curl -fsSL ${BASE}/kerno_${VERSION}_linux_amd64.tar.gz -o kerno.tar.gz
sha256sum --check --ignore-missing checksums.txt
```

### Inspect the SBOM

```bash
VERSION=v0.1.0

# Download SBOM
curl -fsSL https://github.com/optiqor/kerno/releases/download/${VERSION}/kerno_${VERSION}_sbom.cyclonedx.json \
| jq '.metadata.component, [.components[].name]'

# Verify SBOM attestation
cosign verify-attestation ghcr.io/optiqor/kerno:${VERSION} \
--type cyclonedx \
--certificate-identity-regexp '^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
| jq '.payload | @base64d | fromjson | .predicate.metadata'
```

### Install cosign

```bash
brew install cosign # macOS
go install github.com/sigstore/cosign/v2/cmd/cosign@latest # Go
```

---

## Contributing

Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for:
Expand Down
78 changes: 75 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,78 @@ If you discover a security vulnerability in Kerno, please report it responsibly:
| Previous minor | ✅ (security fixes only) |
| Older | ❌ |

---

## Release Artifact Signing & Verification

Kerno uses **keyless Sigstore signing** for all release artifacts. No private key — signing is performed by the GitHub Actions OIDC identity and recorded in the public [Rekor](https://rekor.sigstore.dev) transparency log.

### Signing identity

| Field | Value |
|-------|-------|
| **OIDC issuer** | `https://token.actions.githubusercontent.com` |
| **Certificate identity (regexp)** | `^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v` |
| **Transparency log** | Sigstore / Rekor (public instance) |
| **Key management** | Keyless — no private key; GitHub OIDC ephemeral cert |

### What is signed

| Artifact | How | Where |
|----------|-----|-------|
| Container image (`:v*` tag) | `cosign sign` | OCI registry + Rekor |
| Container image (`:latest` tag) | `cosign sign` | OCI registry + Rekor |
| `checksums.txt` (covers all binaries & archives) | `cosign sign-blob` | Release assets (`.sig` + `.pem`) |
| CycloneDX SBOM | `cosign attest --type cyclonedx` | OCI registry + Rekor |

### Verify a container image

```bash
cosign verify ghcr.io/optiqor/kerno:v0.1.0 \
--certificate-identity-regexp '^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```

### Verify binary checksums

```bash
VERSION=v0.1.0
BASE=https://github.com/optiqor/kerno/releases/download/${VERSION}

curl -fsSL ${BASE}/checksums.txt -o checksums.txt
curl -fsSL ${BASE}/checksums.txt.sig -o checksums.txt.sig
curl -fsSL ${BASE}/checksums.txt.pem -o checksums.txt.pem

cosign verify-blob checksums.txt \
--signature checksums.txt.sig \
--certificate checksums.txt.pem \
--certificate-identity-regexp '^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com

curl -fsSL ${BASE}/kerno_${VERSION}_linux_amd64.tar.gz -o kerno.tar.gz
sha256sum --check --ignore-missing checksums.txt
```

### Verify the SBOM attestation

```bash
cosign verify-attestation ghcr.io/optiqor/kerno:v0.1.0 \
--type cyclonedx \
--certificate-identity-regexp '^https://github\.com/optiqor/kerno/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
| jq '.payload | @base64d | fromjson | .predicate.metadata'
```

### Reporting a tampered artifact

Agar `cosign verify` fail ho kisi official release tag pe — **artifact use mat karo** aur turant report karo:
Comment thread
Kokila-chandrakar marked this conversation as resolved.

1. Email karo **team.optiqor@gmail.com** — subject: `[SECURITY] Possible tampered artifact`
2. `cosign verify` ka poora output aur exact image digest ya file hash include karo
3. We will investigate and post a GitHub Security Advisory if confirmed

---

## Security Considerations for Kerno

Kerno runs with elevated privileges (root or `CAP_BPF` + `CAP_PERFMON` + `CAP_SYS_PTRACE`) to load eBPF programs into the kernel. This means:
Expand All @@ -53,12 +125,12 @@ Kerno runs with elevated privileges (root or `CAP_BPF` + `CAP_PERFMON` + `CAP_SY

## Disclosure Policy

- We follow [coordinated vulnerability disclosure](https://vuls.cert.org/confluence/display/Wiki/Vulnerability+Disclosure+Policy).
- We follow [coordinated vulnerability disclosure](https://certcc.github.io/CERT-Guide-to-CVD/).
- We will credit reporters in security advisories (unless anonymity is requested).
- We use GitHub Security Advisories for publishing fixes.

## Contact

- **Security reports:** team.optiqor@gmail.com
- **Security reports:** team.optiqor@gmail.com
- **General questions:** GitHub Discussions
- **Maintainer:** Shivam Kumar (@btwshivam)
- **Maintainer:** Shivam Kumar (@btwshivam)
Loading