ๆƒฏๆ€ง่šๅˆ ้ซ˜ๆ•ˆ่ฟฝ่ธชๅ’Œ้˜…่ฏปไฝ ๆ„Ÿๅ…ด่ถฃ็š„ๅšๅฎขใ€ๆ–ฐ้—ปใ€็ง‘ๆŠ€่ต„่ฎฏ
้˜…่ฏปๅŽŸๆ–‡ ๅœจๆƒฏๆ€ง่šๅˆไธญๆ‰“ๅผ€

ๆŽจ่่ฎข้˜…ๆบ

P
Proofpoint News Feed
ไบ‘้ฃŽ็š„ BLOG
ไบ‘้ฃŽ็š„ BLOG
Apple Machine Learning Research
Apple Machine Learning Research
Hugging Face - Blog
Hugging Face - Blog
OSCHINA ็คพๅŒบๆœ€ๆ–ฐๆ–ฐ้—ป
OSCHINA ็คพๅŒบๆœ€ๆ–ฐๆ–ฐ้—ป
Google DeepMind News
Google DeepMind News
้’›ๅช’ไฝ“๏ผšๅผ•้ข†ๆœชๆฅๅ•†ไธšไธŽ็”Ÿๆดปๆ–ฐ็Ÿฅ
้’›ๅช’ไฝ“๏ผšๅผ•้ข†ๆœชๆฅๅ•†ไธšไธŽ็”Ÿๆดปๆ–ฐ็Ÿฅ
่ฎฉๅฐไบงๅ“็š„็‹ฌ็ซ‹ๅ˜็Žฐๆ›ด็ฎ€ๅ• - ezindie.com
่ฎฉๅฐไบงๅ“็š„็‹ฌ็ซ‹ๅ˜็Žฐๆ›ด็ฎ€ๅ• - ezindie.com
้›ทๅณฐ็ฝ‘
้›ทๅณฐ็ฝ‘
B
Blog
ๆœˆๅ…‰ๅšๅฎข
ๆœˆๅ…‰ๅšๅฎข
ๅš
ๅšๅฎขๅ›ญ - ใ€ๅฝ“่€็‰นใ€‘
WordPressๅคงๅญฆ
WordPressๅคงๅญฆ
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Jina AI
Jina AI
ๅš
ๅšๅฎขๅ›ญ - Franky
MyScale Blog
MyScale Blog
H
Hackread โ€“ Cybersecurity News, Data Breaches, AI and More
Last Week in AI
Last Week in AI
B
Blog RSS Feed
H
Help Net Security

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Donโ€™t Fail โ€” They Drift Spilling beans for how i learn for exam๐Ÿ˜"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" โ€” What Actually Happened Comfy Cloudโ€™s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions โ€” here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components โ€” Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cรณmo construรญ un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 ๐Ÿš€ I Built an Ethical Hacking Scanner Tool โ€“ Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points โ€” Here's What I Found About How Markets Really Move EcoTrack AI โ€” Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
๐Ÿ”Enforcing image provenance in Kubernetes using Cosign + ...
Matteo Vitali ยท 2026-05-04 ยท via DEV Community

Matteo Vitali

What if your Kubernetes cluster simply refused to run unsigned images?

I spent some time experimenting with enforcing image provenance in a small Kubernetes setup using MicroK8s.

The idea was simple:

Only container images with valid cryptographic signatures are allowed to run in the cluster.

For this I used:

  • GitLab CI/CD (build + signing pipeline)
  • Cosign / Sigstore (image signing)
  • Kyverno (admission control)
  • MicroK8s (local cluster)

Repo: https://github.com/trottomv/microk8s-cosign-kyverno


Why this matters

Most Kubernetes setups still rely on mutable image tags like latest, which introduces supply chain risks:

  • No guarantee of image origin
  • No binding between CI pipeline and deployed artifact
  • Risk of registry or tag mutation

So the trust gap is basically:

build time โ†’ registry โ†’ runtime


Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚        GitLab CI/CD          โ”‚
โ”‚                              โ”‚
โ”‚  โ€ข Build container image     โ”‚
โ”‚  โ€ข Push to OCI registry      โ”‚
โ”‚  โ€ข Sign image (Cosign)       โ”‚
โ”‚  โ€ข Publish signature         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚
               โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚        OCI Registry          โ”‚
โ”‚   (image + signature)        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚
               โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Kubernetes (MicroK8s)      โ”‚
โ”‚                              โ”‚
โ”‚  Kyverno Admission Controllerโ”‚
โ”‚  โ€ข verify Cosign signature   โ”‚
โ”‚  โ€ข resolve image digest      โ”‚
โ”‚  โ€ข enforce policy decision   โ”‚
โ”‚                              โ”‚
โ”‚  โ†’ allow / reject Pod        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜


CI/CD: GitLab as trust origin

The image is built and signed inside GitLab CI/CD.

Example pipeline:

stages:
  - build
  - sign

build:
  stage: build
  script:
    - docker build -t $IMAGE:$TAG .
    - docker push $IMAGE:$TAG

sign:
  stage: sign
  script:
    - cosign sign --key $COSIGN_KEY $IMAGE:$TAG

The rule is simple:

If it doesnโ€™t come from CI, it doesnโ€™t get signed.

This effectively makes the CI pipeline the root of trust for all artifacts.


Signing with Cosign

Cosign attaches a cryptographic signature to OCI images.

cosign sign --key cosign.key ghcr.io/<repo>/<image>:<tag>

Verification:

cosign verify --key cosign.pub ghcr.io/<repo>/<image>:<tag>

Signatures are stored directly in the OCI registry as artifacts.


Kyverno enforcement

Kyverno enforces image verification at admission time using a ClusterPolicy.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-signed-images
spec:
  validationFailureAction: Enforce
  background: false

  rules:
    - name: check-signature
      match:
        resources:
          kinds:
            - Pod

      verifyImages:
        - imageReferences:
            - "ghcr.io/<repo>/*"
          attestors:
            - entries:
                - keys:
                    publicKeys: |
                      -----BEGIN PUBLIC KEY-----
                      ...
                      -----END PUBLIC KEY-----

At runtime Kyverno:

  1. Extracts image reference from Pod
  2. Resolves immutable digest
  3. Fetches Cosign signature from registry
  4. Verifies signature
  5. Allows or denies Pod creation

What happens in practice

Unsigned image

  • No valid signature found
  • Kyverno rejects Pod at admission

Signed image

  • Signature verified successfully
  • Pod is admitted into the cluster

The interesting bit:

even if someone manually pushes an image to the registry, it still wonโ€™t run.

The cluster doesnโ€™t trust the registry โ€” it trusts the signature.


Why MicroK8s

MicroK8s was used as a lightweight lab environment to:

  • test Kyverno policies locally
  • simulate admission control behavior
  • iterate quickly on Cosign integration

Key takeaways

  • GitLab CI/CD becomes a trust anchor when combined with Cosign
  • Kyverno enforces security at admission time, not runtime
  • OCI registry acts as a provenance carrier
  • End-to-end supply chain security is achievable with minimal tooling

Closing thought

This experiment shows how Kubernetes supply chain security can be enforced end-to-end using:

  • GitLab CI/CD for build and signing
  • Cosign for cryptographic provenance
  • Kyverno for policy enforcement

Result:

Only verified and signed workloads can run in the cluster.


Repository

https://github.com/trottomv/microk8s-cosign-kyverno