DevSecOps-projecten

CI/CD en supply-chain-beveiliging

Veilige delivery-pipeline

Een kleine Python-API, geleverd op de DevSecOps-manier: elke wijziging wordt getest en gescand, het image wordt één keer gebouwd, ondertekend en via GitOps uitgerold, en het cluster draait alleen images die deze pipeline heeft ondertekend.

  • GitHub Actions
  • Python
  • Docker
  • Trivy
  • Semgrep
  • gitleaks
  • Syft
  • cosign
  • SLSA
  • Kustomize
  • Argo CD
  • Kyverno
  • Kubernetes

In het kort

6
automatische beveiligingscontroles
0
opgeslagen ondertekeningssleutels
1
menselijke goedkeuring voor productie
< 3 min
van merge tot dev

Het doel

Veel aanvallen op software breken vandaag niet de app, maar de manier waarop die gebouwd en geleverd wordt: een gelekt token, een vergiftigd image of een handmatige wijziging in productie. Het doel: een leversysteem waarin elke stap automatisch, gecontroleerd en traceerbaar is, en waarin productie alleen accepteert wat de pipeline heeft gebouwd en ondertekend. De app is bewust klein; de waarde zit in het systeem eromheen.

Wat het laat zien

Continuous integration
ruff (met bandit-regels), pytest met een coverage-grens van 90 %, een smoke-test van de echte container.
Shift-left-beveiliging
gitleaks voor secrets, Semgrep voor de code, Trivy en kubeconform voor de Dockerfile en de Kubernetes-bestanden.
Supply chain
Trivy-image-scan, Syft-SBOM (CycloneDX), cosign-ondertekening zonder sleutel, SBOM-attestatie, SLSA-build-provenance.
Levering
Kustomize-overlays, het image vastgezet op digest, Argo CD synchroniseert dev zelf, productie via een beoordeelde pull request.
Runtime-beveiliging
Pod Security "restricted", geen root, alleen-lezen bestandssysteem, geen capabilities, seccomp, default-deny netwerkbeleid.
Admission control
Kyverno laat alleen images toe die door deze repository zijn ondertekend, en alleen pods met limieten en probes.

Architectuur

Eén wijziging, van de ontwikkelaar tot het cluster. De pipeline krijgt nooit toegang tot het cluster: Argo CD haalt de wijziging uit Git.

From commit to production: checks, build, scan, sign, GitOps, admissionGitHub Actions (every change)Developerbranch + PRTests + lintruff · pytest ≥ 90 %SecretsgitleaksSASTSemgrepIaCTrivy config · kubeconformBuild + smoke testdocker · non-rootruns the containerScan + SBOMTrivy image (gate)Syft CycloneDXSign + attestcosign keyless (OIDC)SBOM + SLSA provenanceGHCRimage by digestsha256:…Git: overlays/devcommit by the pipelineGit: overlays/prodpull request + human mergecommit digestpromotion PRKubernetes clusterArgo CDpulls from Gitno CI credentialsKyvernosignature + identitylimits + probesshop-api podsrestricted PSAread-only, non-rootdefault-deny networkpull

Stap voor stap

  1. Pull request

    Lint, unit-tests, secret-scan, SAST en IaC-controles draaien tegelijk. Het image wordt gebouwd, getest, gescand en krijgt een SBOM. Er wordt nog niets gepubliceerd.

  2. Merge naar main

    Dezelfde controles draaien opnieuw. Het image gaat op digest naar GHCR, wordt ondertekend met cosign (zonder sleutel, met de GitHub-identiteit) en krijgt een SBOM-attestatie en SLSA-provenance.

  3. Uitrol naar dev

    De pipeline schrijft de nieuwe digest in de dev-overlay. Argo CD ziet de commit en synchroniseert dev zelf.

  4. Naar productie

    De pipeline opent een pull request voor de prod-overlay met dezelfde digest. Een mens beoordeelt en merget hem: die merge is de release. Terugdraaien = git revert.

  5. Admission

    Voordat een pod start, controleert Kyverno de handtekening en de identiteit van de pipeline, en de limieten en probes. Al het andere wordt geweigerd.

Bewijs uit een echte run

Run op de branch main op 2026-10-27, uit GitHub Actions. Tijd per job:

  • Lint and unit tests 12s
  • Secret scan (gitleaks) 10s
  • SAST (semgrep) 33s
  • IaC and manifest checks 15s
  • Build, scan, SBOM, sign 1m 53s
  • Deploy to dev (GitOps commit) 4s

Open deze run (opens in a new tab) · deploy(dev): shop-api bf471203925f

Beveiligingsmaatregelen

MaatregelWat het tegenhoudt
gitleaks in pre-commit en CIWachtwoorden en tokens in Git.
Semgrep SASTInjectie, onveilige functies en zwakke cryptografie in de code.
Trivy-image-scan met grensBekende kritieke kwetsbaarheden uitleveren.
Digest in plaats van tagEen ander image achter dezelfde tag.
cosign zonder sleutel + KyvernoImages die de pipeline niet heeft gebouwd en ondertekend.
Pull-gebaseerde GitOpsGestolen CI-gegevens die het cluster bereiken.
Restricted pods + default-deny netwerkUitbreken en verspreiden vanuit één gehackte pod.
Actions vastgezet op commit-SHA'sEen gewijzigde externe action in de pipeline.

Probeer het zelf

make install test          # Python 3.12+: lint, tests, 90 % coverage gate
make run                   # http://127.0.0.1:8080/docs
docker compose up --build  # the hardened container: read-only, non-root, no capabilities
make kind-up               # local Kubernetes with ingress, Kyverno and Argo CD

# check the signature of a published image (keyless, GitHub OIDC identity)
cosign verify ghcr.io/s0sta/secure-delivery-pipeline@sha256:… \
  --certificate-identity-regexp 'https://github.com/s0sta/secure-delivery-pipeline/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Wat ik geleerd heb

  • Eerlijke grenzen worden geaccepteerd: stop eerst alleen bij nieuwe kritieke bevindingen en leg de lat dan stap voor stap hoger.
  • Een handtekening telt alleen als iets hem controleert: het beleid in het cluster is de echte maatregel.
  • Een echte CI-run vindt wat lokale tests missen: een verwijderde tool-release, een ontbrekend pad, een repository-instelling.
Volgende casestudy Azure k3s-platform