Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
143ab1a
refactor: move IMA operator into internal/attest package
dorser Jul 3, 2026
d954afa
refactor: rename binary-attestation gadget to sigward
dorser Jul 3, 2026
48f30ba
feat: add sigward command
dorser Jul 3, 2026
da8b874
refactor: drop attestation gadget from micromize command
dorser Jul 3, 2026
690a31f
feat: add sigward helm chart
dorser Jul 3, 2026
0811814
build: add sigward image and split release wiring
dorser Jul 3, 2026
542b3ce
refactor: remove sbom registry-auth from micromize chart
dorser Jul 3, 2026
d653d44
docs: document micromize and sigward products
dorser Jul 3, 2026
f002ba4
ci: build the sigward image in CI
dorser Jul 3, 2026
8c7ab00
fix: correct sbom path normalization and length check
dorser Jul 3, 2026
26e80b9
fix(helm): point sigward chart notes at the monorepo
dorser Jul 3, 2026
9a8f4a9
refactor: share namespace filter helper across commands
dorser Jul 3, 2026
3f436af
refactor: clarify sbom path safety helper naming
dorser Jul 3, 2026
89c253d
build: align conform version with ci
dorser Jul 3, 2026
6d09606
refactor(helm): narrow owner-reference enrichment rbac
dorser Jul 3, 2026
2093c56
build: align ig and go toolchain versions with go.mod
dorser Jul 3, 2026
1c0d6bb
build: bump inspektor-gadget to v0.53.2
dorser Jul 3, 2026
eae57ee
build: upgrade go to 1.26 ahead of inspektor-gadget requirement
dorser Jul 3, 2026
774fb59
docs(helm): correct SYS_PTRACE capability comment
dorser Jul 3, 2026
362addd
fix: derive agent namespace at runtime for self-exclusion
dorser Jul 3, 2026
134dacf
fix(helm): add exemptLabel to values schema
dorser Jul 3, 2026
146431e
feat: attest sigward's own namespace
dorser Jul 3, 2026
532b226
build: rename Dockerfile to Dockerfile.micromize
dorser Jul 3, 2026
8dc769b
fix: avoid leading comma when appending exempt namespaces
dorser Jul 3, 2026
c5c0b68
refactor: make namespace file path injectable for tests
dorser Jul 3, 2026
7ce86ec
fix(helm): require image.tag in values schema
dorser Jul 3, 2026
c81484e
docs: correct sigward filter-namespaces help text
dorser Jul 3, 2026
34e1d35
build: use go 1.26 directive with toolchain go1.26.4
dorser Jul 3, 2026
a5f181c
fix: close superseded inner map to avoid bpf fd leak
dorser Jul 4, 2026
32a84ec
fix: trim the self-namespace in the namespace filter
dorser Jul 4, 2026
19b0e38
fix: ignore empty --filter-image-digest values
dorser Jul 4, 2026
695c106
fix: align gadget image paths under /gadgets/
dorser Jul 4, 2026
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
7 changes: 5 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,8 @@ jobs:
- name: Test
run: go test ./...

- name: Build Docker image
run: docker build .
- name: Build Micromize image
run: docker build -f Dockerfile.micromize .

- name: Build Sigward image
run: docker build -f Dockerfile.sigward .
45 changes: 43 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
IG_VERSION: v0.47.0
IG_VERSION: v0.53.2

jobs:
release-gadgets:
Expand All @@ -24,7 +24,7 @@ jobs:

strategy:
matrix:
gadget: [fs-restrict, cap-restrict, ptrace-restrict]
gadget: [fs-restrict, cap-restrict, ptrace-restrict, socket-restrict, sigward]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -109,8 +109,49 @@ jobs:
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.micromize
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG_NAME }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
platforms: linux/amd64,linux/arm64

release-sigward:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set TAG_NAME
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "TAG_NAME=${{ inputs.tag_name }}" >> $GITHUB_ENV
else
echo "TAG_NAME=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
fi

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Sigward
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.sigward
push: true
tags: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/sigward:${{ env.TAG_NAME }}
${{ env.REGISTRY }}/${{ github.repository_owner }}/sigward:latest
platforms: linux/amd64,linux/arm64
12 changes: 6 additions & 6 deletions Dockerfile → Dockerfile.micromize
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM ghcr.io/inspektor-gadget/gadget-builder:main AS gadget-builder

ARG IG_VERSION=v0.47.0
ARG IG_VERSION=v0.53.2
ARG IMAGE_TAG=dev
ARG TARGETOS
ARG TARGETARCH
Expand All @@ -15,20 +15,20 @@ COPY gadgets gadgets

# Build gadgets
RUN mkdir -p build/gadgets && \
for gadget in fs-restrict cap-restrict ptrace-restrict socket-restrict binary-attestation; do \
for gadget in fs-restrict cap-restrict ptrace-restrict socket-restrict; do \
echo "Building gadget: $gadget" && \
ig image build \
--local \
-t ghcr.io/micromize-dev/micromize/${gadget}:${IMAGE_TAG} \
-t ghcr.io/micromize-dev/micromize/gadgets/${gadget}:${IMAGE_TAG} \
gadgets/${gadget} && \
ig image export \
ghcr.io/micromize-dev/micromize/${gadget}:${IMAGE_TAG} \
ghcr.io/micromize-dev/micromize/gadgets/${gadget}:${IMAGE_TAG} \
build/gadgets/${gadget}.tar; \
done

FROM --platform=$BUILDPLATFORM golang:1.26.2-alpine AS builder
FROM --platform=$BUILDPLATFORM golang:1.26.4-alpine AS builder

ARG IG_VERSION=v0.47.0
ARG IG_VERSION=v0.53.2
ARG IMAGE_TAG=dev
ARG TARGETOS
ARG TARGETARCH
Expand Down
87 changes: 87 additions & 0 deletions Dockerfile.sigward
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
FROM ghcr.io/inspektor-gadget/gadget-builder:main AS gadget-builder

ARG IG_VERSION=v0.53.2
ARG IMAGE_TAG=dev
ARG TARGETOS
ARG TARGETARCH

# Install ig
RUN wget -qO- https://github.com/inspektor-gadget/inspektor-gadget/releases/download/${IG_VERSION}/ig-${TARGETOS}-${TARGETARCH}-${IG_VERSION}.tar.gz \
| tar -xz -C /usr/local/bin ig

WORKDIR /app
COPY include/micromize /usr/include/micromize
COPY gadgets gadgets

# Build the sigward attestation gadget
RUN mkdir -p build/gadgets && \
for gadget in sigward; do \
echo "Building gadget: $gadget" && \
ig image build \
--local \
-t ghcr.io/micromize-dev/micromize/gadgets/${gadget}:${IMAGE_TAG} \
gadgets/${gadget} && \
ig image export \
ghcr.io/micromize-dev/micromize/gadgets/${gadget}:${IMAGE_TAG} \
build/gadgets/${gadget}.tar; \
done

FROM --platform=$BUILDPLATFORM golang:1.26.4-alpine AS builder

ARG IG_VERSION=v0.53.2
ARG IMAGE_TAG=dev
ARG TARGETOS
ARG TARGETARCH

WORKDIR /app

# Cache dependencies
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Copy the built gadget where embeds.go expects it (cmd/sigward/build/)
RUN mkdir -p cmd/sigward/build
COPY --from=gadget-builder /app/build/gadgets/sigward.tar cmd/sigward/build/

# Build the static binary
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-tags release \
-ldflags "-X github.com/inspektor-gadget/inspektor-gadget/internal/version.version=${IG_VERSION} -X main.Version=${IMAGE_TAG} -w -s -extldflags '-static'" \
-o /sigward \
./cmd/sigward

# Build the image
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /sigward /sigward

# Access to kernel debug filesystem (tracefs)
VOLUME ["/sys/kernel/debug"]

# Access to kernel security configuration (LSM)
VOLUME ["/sys/kernel/security"]

# Access to BPF filesystem for map pinning
VOLUME ["/sys/fs/bpf"]

# Access to cgroup hierarchy
VOLUME ["/sys/fs/cgroup"]

# Access to host process information
VOLUME ["/host/proc"]

# Access to host system information
VOLUME ["/host/sys"]

# Access to host binaries and libraries
VOLUME ["/host/bin"]
VOLUME ["/host/usr"]

# Access to host runtime files (sockets, etc.)
VOLUME ["/host/run"]

ENV HOST_ROOT=/host
ENTRYPOINT ["/sigward"]
35 changes: 20 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ IMAGE_TAG ?= $(TAG)
CLANG_FORMAT ?= clang-format
OUTPUT_DIR := dist
GOARCHS := amd64 arm64
LDFLAGS := -X github.com/inspektor-gadget/inspektor-gadget/internal/version.version=v0.47.0 \
LDFLAGS := -X github.com/inspektor-gadget/inspektor-gadget/internal/version.version=v0.53.2 \
-X main.Version=$(IMAGE_TAG) \
-w -s -extldflags "-static"
GADGETS := fs-restrict cap-restrict ptrace-restrict socket-restrict binary-attestation
CONFORM_VERSION ?= v0.1.0-alpha.30
GADGETS := fs-restrict cap-restrict ptrace-restrict socket-restrict sigward
CONFORM_VERSION ?= v0.1.0-alpha.31

# This version number must be kept in sync with CI workflow lint one.
LINTER_IMAGE ?= golangci/golangci-lint:v2.10.1
Expand Down Expand Up @@ -60,12 +60,12 @@ build-app: test $(GOARCHS)

$(GADGETS):
sudo -E IG_SOURCE_PATH=$(CURDIR) ig image build \
-t $(CONTAINER_REPO)/$@:$(IMAGE_TAG) \
-t $(CONTAINER_REPO)/gadgets/$@:$(IMAGE_TAG) \
--update-metadata gadgets/$@

mkdir -p build/gadgets

sudo -E ig image export $(CONTAINER_REPO)/$@:$(IMAGE_TAG) build/gadgets/$@.tar
sudo -E ig image export $(CONTAINER_REPO)/gadgets/$@:$(IMAGE_TAG) build/gadgets/$@.tar

$(GOARCHS):
@mkdir -p $(OUTPUT_DIR)
Expand All @@ -74,29 +74,34 @@ $(GOARCHS):
# Copy source to build/src
cp -r cmd internal go.mod go.sum build/src/

# Copy gadgets to where main.go expects them
# micromize embeds the boundary gadgets
mkdir -p build/src/cmd/micromize/build
cp build/gadgets/*.tar build/src/cmd/micromize/build/
cp build/gadgets/fs-restrict.tar build/gadgets/cap-restrict.tar build/gadgets/ptrace-restrict.tar build/gadgets/socket-restrict.tar build/src/cmd/micromize/build/

# Build
# sigward embeds its attestation gadget
mkdir -p build/src/cmd/sigward/build
cp build/gadgets/sigward.tar build/src/cmd/sigward/build/

# Build both product binaries
cd build/src && GOOS=linux GOARCH=$@ CGO_ENABLED=0 go build -tags release -ldflags "$(LDFLAGS)" -o ../../$(OUTPUT_DIR)/micromize-linux-$@ ./cmd/micromize
cd build/src && GOOS=linux GOARCH=$@ CGO_ENABLED=0 go build -tags release -ldflags "$(LDFLAGS)" -o ../../$(OUTPUT_DIR)/sigward-linux-$@ ./cmd/sigward

.PHONY: run-fs-restrict
run-fs-restrict:
sudo -E ig run $(CONTAINER_REPO)/fs-restrict:$(IMAGE_TAG) $$PARAMS
sudo -E ig run $(CONTAINER_REPO)/gadgets/fs-restrict:$(IMAGE_TAG) $$PARAMS

.PHONY: run-cap-restrict
run-cap-restrict:
sudo -E ig run $(CONTAINER_REPO)/cap-restrict:$(IMAGE_TAG) $$PARAMS
sudo -E ig run $(CONTAINER_REPO)/gadgets/cap-restrict:$(IMAGE_TAG) $$PARAMS

.PHONY: run-socket-restrict
run-socket-restrict:
sudo -E ig run $(CONTAINER_REPO)/socket-restrict:$(IMAGE_TAG) $$PARAMS
sudo -E ig run $(CONTAINER_REPO)/gadgets/socket-restrict:$(IMAGE_TAG) $$PARAMS

.PHONY: push
push:
for gadget in $(GADGETS); do \
sudo -E ig image push $(CONTAINER_REPO)/$$gadget:$(IMAGE_TAG); \
sudo -E ig image push $(CONTAINER_REPO)/gadgets/$$gadget:$(IMAGE_TAG); \
done

.PHONY: clang-format
Expand All @@ -114,7 +119,7 @@ dev-build: ## Build Docker image for dev deployment
ifeq ($(strip $(DEV_REGISTRY)),)
$(error DEV_REGISTRY is required. Set it via environment or argument: make dev-build DEV_REGISTRY=myacr.azurecr.io)
endif
docker build --no-cache -t $(DEV_REGISTRY)/micromize:$(DEV_TAG) .
docker build --no-cache -f Dockerfile.micromize -t $(DEV_REGISTRY)/micromize:$(DEV_TAG) .

.PHONY: dev-push
dev-push: ## Push dev image to registry
Expand Down Expand Up @@ -150,8 +155,8 @@ dev-logs: ## Tail logs from all dev pods
dev-status: ## Show dev pod status
kubectl get pods -n $(DEV_NAMESPACE) -l app.kubernetes.io/name=micromize -o wide

IG_VERSION ?= v0.49.1
IG_ARCHIVE_SHA256 ?= 1cc186b4ebe476da9c89b6ff2f38234b13d4eae3d2a3b597b3647393c2a223c0
IG_VERSION ?= v0.53.2
IG_ARCHIVE_SHA256 ?= 4eb164b04d2fbb2fc28b763a4aff9a81a4830f9e60c7c91c9e1206419ed7cf46
SKIP_CHECKSUM ?= 0
.PHONY: update-includes
update-includes:
Expand Down
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ Tools may detect this. Few eliminate it.

## Philosophy

Micromize doesn't care what happens inside the container. Instead, it enforces the boundaries. We don't scan for cryptominers because with Micromize, unauthorized binaries can't execute in the first place. You can't effectively protect against every poorly written application, but you can guarantee that nothing runs unless it was part of the original image.
Micromize doesn't care what happens inside the container. Instead, it enforces the boundaries. You can't effectively protect against every poorly written application, but you can guarantee a container stays within the limits of what a container is meant to be.

Micromize assumes containers are immutable, disposable, non-host-mutating, and explicit about privilege.

If your workload violates those assumptions, Micromize blocks it or forces an explicit posture decision.

> Want to go further and guarantee that only the exact, cryptographically signed binaries from your image can execute? See **[Sigward](#sigward)**, the execution-attestation product that ships from this repository.

## What Micromize Does

Today, Micromize attaches eBPF programs to LSM hooks and enforces:
Expand All @@ -31,10 +33,18 @@ Today, Micromize attaches eBPF programs to LSM hooks and enforces:
- **Capability restriction** — prevents privilege escalation via `unshare`/`clone`/`setns`
- **Ptrace blocking** — eliminates ptrace-based debugging/injection attacks
- **Socket restriction** — blocks `AF_ALG` (kernel crypto userspace API) socket usage in containers, mitigating CVE-2026-31431 and related attack surface
- **Execution integrity** — SBOM + runtime hash validation via `bpf_ima_file_hash`

Policies are loaded before container start and enforced at execution time. No runtime replacement. No learning mode. Kernel-native enforcement.

## Sigward

This repository is a monorepo that ships **two** products from a shared codebase:

- **Micromize** (`cmd/micromize`) — the boundary-enforcement agent described above.
- **[Sigward](gadgets/sigward)** (`cmd/sigward`) — execution attestation. Sigward verifies, in the kernel (BPF-LSM + IMA), that every binary and shared object a container runs matches a cryptographically signed SPDX SBOM attached to its image. Anything unattested or tampered with is blocked before it executes.

They are separate deployables — separate binaries, images, and Helm charts (`charts/sigward`) — so Sigward's registry access, credentials, and `CONFIG_IMA` requirement never get forced onto a plain Micromize deployment. Deploy either or both; they compose at the LSM layer.

## Quickstart

### Docker
Expand Down Expand Up @@ -82,7 +92,6 @@ helm install micromize ./charts/micromize \

- Linux kernel 5.18+
- BPF LSM enabled (`CONFIG_BPF_LSM=y`, boot with `lsm=...,bpf`)
- IMA enabled (`CONFIG_IMA=y`) — required for execution integrity via `bpf_ima_file_hash`

## Development

Expand Down
6 changes: 3 additions & 3 deletions charts/micromize/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["list", "watch"]
- apiGroups: ["*"]
- apiGroups: ["", "apps", "batch"]
resources: ["deployments", "replicasets", "statefulsets", "daemonsets", "jobs", "cronjobs", "replicationcontrollers"]
# Required to retrieve the owner references used by the seccomp gadget.
verbs: ["get", "list", "watch", "create"]
# Required to resolve pod owner references for Kubernetes enrichment.
verbs: ["get", "list", "watch"]
{{- end -}}
Loading
Loading