⏱ 48 min. lezen DevSecOps boek

DevSecOps — Beveiliging als geïntegreerd onderdeel van software delivery

Een compleet praktijkboek over DevSecOps: cultuur, security gates, threat modeling, SAST/SCA/DAST, secretsbeheer, policy as code, supply chain security en een volledig uitgewerkte praktijkcasus.

DEVSECOPS

Beveiliging als geïntegreerd onderdeel van software delivery
Een praktische gids met cultuur, principes, diagrammen
en uitvoerbare YAML-voorbeelden voor CI/CD-pijplijnen
Juli 2026

Hoofdstuk 1 — Inleiding: wat is DevSecOps?

Software wordt tegenwoordig sneller gebouwd en vaker uitgeleverd dan ooit tevoren. Waar organisaties vroeger een paar keer per jaar een nieuwe release uitbrachten, gebeurt dat bij veel teams nu meerdere keren per dag. Deze versnelling is grotendeels te danken aan DevOps: de beweging die ontwikkeling (Development) en beheer (Operations) samenbrengt in geautomatiseerde, herhaalbare processen. Maar met deze snelheid ontstaat een nieuw risico: beveiliging kan niet langer een losstaande, langzame stap aan het einde van het traject zijn. Als security pas wordt getoetst vlak voor een release, ontstaat er wrijving, vertraging en frustratie — en vaak worden bevindingen genegeerd omdat de deadline al is vastgelegd.

DevSecOps is het antwoord op dit probleem. Het is geen nieuw team, geen nieuwe tool en geen keurmerk, maar een manier van werken waarin beveiliging een geïntegreerd, geautomatiseerd en gedeeld onderdeel wordt van de volledige softwarelevenscyclus — van de eerste ontwerpschets tot de code die in productie draait en wordt gemonitord. De term is een samentrekking van Development, Security en Operations, en de volgorde van de letters is bewust: security wordt letterlijk tussen development en operations in geplaatst, als iets dat overal bij hoort in plaats van ergens aan het einde wordt toegevoegd.

2026-07-06T09:32:22.554018 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 1.1 — DevSecOps ontstaat op het snijvlak van ontwikkeling, beveiliging en beheer.

1.1 Waarom traditionele beveiliging niet meer volstaat

In de klassieke aanpak werd beveiliging vaak gezien als een poortwachtersfunctie: een apart security-team voerde aan het einde van een project een audit of penetratietest uit, en pas na goedkeuring mocht de software live. Dit model had drie grote nadelen.

  • Snelheid: een audit die weken duurt past niet bij een team dat meerdere keren per dag deployt.
  • Kosten: hoe later een kwetsbaarheid wordt gevonden, hoe duurder het is om deze te herstellen — een fout die in de ontwerpfase tien minuten kost om te corrigeren, kan in productie dagen of weken werk vergen, inclusief hotfixes, communicatie en mogelijk reputatieschade.
  • Verantwoordelijkheid: wanneer beveiliging het exclusieve domein van één team is, voelen ontwikkelaars zich er niet verantwoordelijk voor en ontstaat er een cultuur van "security is niet mijn probleem".
2026-07-06T09:32:22.993888 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 1.2 — Hoe eerder in de levenscyclus een fout wordt gevonden, hoe lager de herstelkosten.

1.2 De kernbelofte van DevSecOps

DevSecOps belooft niet dat er nooit meer kwetsbaarheden zullen ontstaan — dat is een utopie. De belofte is dat kwetsbaarheden sneller, vaker en goedkoper worden gevonden en verholpen, door:

  1. Automatisering: beveiligingscontroles worden zoveel mogelijk geautomatiseerd en in de CI/CD-pijplijn ingebouwd, zodat ze bij elke commit of pull request worden uitgevoerd.
  2. Vroege feedback (shift left): ontwikkelaars krijgen al tijdens het coderen of tijdens de pull request feedback over kwetsbaarheden, in plaats van weken later.
  3. Gedeelde verantwoordelijkheid: beveiliging is niet het exclusieve domein van één team, maar een gedeelde verantwoordelijkheid van ontwikkelaars, security-specialisten en operations-teams.
  4. Continue monitoring (shield right): ook na de deployment blijft een systeem bewaakt, zodat afwijkend gedrag en nieuwe kwetsbaarheden snel worden opgemerkt.
  5. Meetbaarheid: beveiliging wordt met concrete metrics gevolgd, zodat verbetering aantoonbaar is in plaats van een gevoel.
Definitie

DevSecOps is de praktijk waarbij beveiligingsprincipes, -tooling en -verantwoordelijkheden worden geïntegreerd in elke fase van de DevOps-levenscyclus, met als doel software sneller én veiliger te leveren, zonder dat snelheid en veiligheid elkaar uitsluiten.

1.3 Voor wie is dit boek?

Dit e-book is geschreven voor ontwikkelaars, platform- en operations-engineers, security-specialisten, engineering managers en architecten die willen begrijpen hoe DevSecOps in de praktijk werkt — niet alleen op conceptueel niveau, maar ook in concrete, uitvoerbare vorm. Ieder hoofdstuk combineert theorie met praktijkvoorbeelden, diagrammen en YAML-configuraties die direct als uitgangspunt kunnen dienen voor een eigen CI/CD-pijplijn. De voorbeelden zijn platform-onafhankelijk beschreven, met concrete uitwerkingen in GitHub Actions en GitLab CI, twee van de meest gebruikte CI/CD-platformen.

1.4 Opbouw van dit boek

Het boek is opgebouwd volgens de natuurlijke volgorde van de softwarelevenscyclus: we beginnen bij cultuur en principes, gaan via ontwerp en threat modeling naar de pijplijn zelf, behandelen per fase de belangrijkste scanmethoden (SAST, SCA, DAST, IaC-scanning, containerbeveiliging), bespreken vervolgens secretsbeheer, policy-as-code en compliance, en sluiten af met monitoring, metrics, organisatorische verandering en een uitgewerkte praktijkcasus met een volledige pijplijnconfiguratie.

Hoofdstuk 2 — Van DevOps naar DevSecOps

2.1 De opkomst van DevOps

Rond 2009 ontstond de DevOps-beweging als reactie op de muur tussen ontwikkeling en beheer. Ontwikkelaars bouwden software die "werkte op mijn machine", terwijl operations-teams verantwoordelijk waren voor de stabiliteit van productieomgevingen. Deze scheiding leidde tot lange releasecycli, handmatige overdrachten en wederzijds wantrouwen. DevOps introduceerde praktijken als continuous integration, continuous delivery, infrastructure as code en uitgebreide monitoring, met als doel: sneller, betrouwbaarder en met minder wrijving software uitleveren.

2.2 Waarom security aanvankelijk buiten beeld bleef

In de eerste jaren van DevOps lag de nadruk vooral op snelheid en samenwerking tussen Dev en Ops. Security-teams werden vaak niet uitgenodigd aan tafel, deels omdat traditionele beveiligingsprocessen (audits, handmatige reviews, periodieke scans) niet pasten bij het tempo van continuous delivery. Het gevolg was een groeiende kloof: hoe sneller DevOps-teams gingen leveren, hoe verder security achterop raakte. Beveiligingsteams werden gezien als vertragende factor, en "shadow IT" en ongeautoriseerde deployments namen toe.

2.3 De geboorte van DevSecOps

Vanaf ongeveer 2015 begon de term DevSecOps (ook wel SecDevOps of Rugged DevOps genoemd) ingang te vinden. De gedachte was simpel maar ingrijpend: als beveiliging niet kan meebewegen met de snelheid van DevOps, moet beveiliging zelf worden geautomatiseerd en in de pijplijn worden ingebouwd. In plaats van een handmatige poort aan het einde, wordt security een reeks geautomatiseerde controles die parallel aan de ontwikkeling meelopen.

2026-07-06T09:32:22.689745 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 2.1 — De DevSecOps-levenscyclus: security is aanwezig in elke fase, van plan tot monitor.

2.4 Kernverschillen tussen DevOps en DevSecOps

AspectKlassieke DevOpsDevSecOps
Moment van security-toetsingAan het einde, vóór releaseContinu, in elke fase
VerantwoordelijkheidApart security-teamGedeeld door alle teams
ToolingHandmatige scans en auditsGeautomatiseerde scans in de pijplijn
Feedback-snelheidDagen tot wekenSeconden tot minuten
Cultuur"Security als blokkade""Security als enabler"
MeetpuntAantal audits uitgevoerdMean Time To Remediate, aantal kritieke bevindingen

2.5 Shift left én shield right

Twee begrippen komen in vrijwel elk gesprek over DevSecOps terug: shift left en shield right. Shift left betekent dat beveiligingsactiviteiten die traditioneel laat in het proces plaatsvonden, naar voren worden gehaald — denk aan threat modeling tijdens het ontwerp, statische codeanalyse tijdens het schrijven van code, en scans op afhankelijkheden bij elke pull request. Shield right vult dit aan: ook na de deployment blijft het systeem actief bewaakt, met runtime-bescherming, anomaliedetectie en incident response. DevSecOps is dus geen eenmalige verschuiving naar links, maar een cirkel van continue aandacht voor beveiliging, van begin tot eind en weer terug.

"Security is not a gate, it's a guardrail." — Een veelgehoorde uitspraak binnen DevSecOps-gemeenschappen, die de verschuiving samenvat van beveiliging als blokkerende controle naar beveiliging als ondersteunende structuur die teams helpt binnen veilige grenzen snel te bewegen.

Hoofdstuk 3 — Kernprincipes en cultuur

Tooling alleen maakt geen organisatie DevSecOps-volwassen. De meest doorslaggevende factor is cultuur: de manier waarop mensen samenwerken, verantwoordelijkheid nemen en omgaan met fouten. In dit hoofdstuk bespreken we de principes die de basis vormen voor een gezonde DevSecOps-praktijk.

3.1 Gedeelde verantwoordelijkheid

In een DevSecOps-cultuur is beveiliging niet het exclusieve domein van een centraal security-team. Ontwikkelaars zijn verantwoordelijk voor het schrijven van veilige code en het oplossen van bevindingen uit geautomatiseerde scans. Platform- en operations-teams zijn verantwoordelijk voor het hardenen van infrastructuur en het bewaken van productieomgevingen. Het security-team verschuift van uitvoerder naar facilitator: het stelt beleid op, kiest en beheert tooling, biedt training en treedt op als expert bij complexe vraagstukken.

2026-07-06T09:32:23.499566 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 3.1 — Verantwoordelijkheden zijn verdeeld, maar overlappen in een gedeelde kern.

3.2 Security champions

Een bewezen praktijk is het aanstellen van security champions: ontwikkelaars binnen een team die affiniteit hebben met beveiliging en als eerste aanspreekpunt fungeren. Zij hoeven geen beveiligingsexperts te zijn, maar fungeren als brug tussen het security-team en het ontwikkelteam, signaleren risico's vroegtijdig en helpen collega's bij het interpreteren van scanresultaten.

3.3 Automatiseer wat herhaalbaar is

Elke controle die een mens herhaaldelijk en op dezelfde manier uitvoert, is een kandidaat voor automatisering. Handmatige controles zijn foutgevoelig, inconsistent en schalen niet. Geautomatiseerde controles daarentegen zijn consistent, snel en kunnen bij elke wijziging opnieuw worden uitgevoerd zonder extra kosten. Dit betekent niet dat mensen overbodig worden: complexe risicoanalyses, architecturale beslissingen en het interpreteren van resultaten in context blijven mensenwerk.

3.4 Fail fast, fail safe

Een pijplijn die een kritieke kwetsbaarheid detecteert, moet de build kunnen blokkeren ("fail the build") vóórdat de wijziging verder in de keten terechtkomt. Dit klinkt streng, maar voorkomt dat kwetsbaarheden zich opstapelen. Belangrijk is wel dat deze poorten proportioneel zijn: niet elke bevinding met lage ernst hoeft een build te blokkeren. Een gebalanceerd beleid onderscheidt tussen ernstniveaus en bepaalt per niveau of een bevinding blokkerend is, een waarschuwing oplevert, of enkel wordt gelogd.

3.5 Beveiliging als continu proces, niet als project

Beveiliging heeft geen eindpunt. Nieuwe kwetsbaarheden worden dagelijks ontdekt in bestaande software, aanvalstechnieken evolueren, en de omgeving van een systeem verandert voortdurend. Een DevSecOps-praktijk moet daarom worden ingericht als continu proces: periodieke herevaluatie van bedreigingsmodellen, regelmatige updates van scanregels, en een cultuur die leert van elk incident.

3.6 Psychologische veiligheid en een blamefree cultuur

Wanneer een kwetsbaarheid of incident wordt ontdekt, is de eerste vraag niet "wie heeft dit veroorzaakt?", maar "wat kunnen we hiervan leren en hoe voorkomen we herhaling?". Een cultuur waarin mensen bang zijn om fouten te melden, leidt tot verborgen problemen die later veel groter en duurder worden. Blameless post-mortems — waarin het proces en het systeem centraal staan, niet de persoon — zijn een kernonderdeel van een volwassen DevSecOps-cultuur.

Praktijktip

Begin niet met het kopen van dure tooling. Begin met één geautomatiseerde scan (bijvoorbeeld een dependency-scan) in één pijplijn, laat het team de waarde ervaren, en breid vervolgens stapsgewijs uit. Cultuurverandering ontstaat door herhaalde, kleine, zichtbare successen.

Hoofdstuk 4 — De DevSecOps-pijplijn en security gates

De CI/CD-pijplijn (Continuous Integration / Continuous Delivery) is het technische hart van DevSecOps. Elke keer dat een ontwikkelaar code commit, doorloopt deze een reeks geautomatiseerde stappen: bouwen, testen, scannen en uiteindelijk uitrollen. In een DevSecOps-pijplijn worden op strategische punten beveiligingscontroles (security gates) toegevoegd, die de pijplijn kunnen blokkeren als er een probleem wordt gevonden.

2026-07-06T09:32:22.849998 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 4.1 — Een representatieve CI/CD-pijplijn met geïntegreerde security gates.

4.1 De belangrijkste soorten security gates

AfkortingBetekenisWanneer in de pijplijn
SASTStatic Application Security Testing — analyse van broncode zonder deze uit te voerenBij elke commit / pull request
SCASoftware Composition Analysis — scannen van open source afhankelijkhedenBij elke commit / build
Secrets scanDetecteren van per ongeluk gecommitte wachtwoorden en sleutelsBij elke commit
Image scanScannen van container-images op kwetsbaarhedenNa build, vóór push naar registry
IaC scanScannen van infrastructuurcode (Terraform, Helm, Kubernetes-manifests)Bij wijziging van infrastructuurcode
DASTDynamic Application Security Testing — testen van een draaiende applicatieIn een staging-omgeving
Policy-as-codeAutomatische afdwinging van organisatiebeleidVóór deployment

4.2 Blokkerend versus signalerend

Niet elke bevinding moet een pijplijn stopzetten. Een veelgebruikte aanpak is het werken met ernstniveaus (bijvoorbeeld critical, high, medium, low) waarbij alleen bevindingen boven een bepaalde drempel de build blokkeren. Bevindingen onder de drempel worden gelogd en getoond in een dashboard, maar blokkeren de release niet. Deze aanpak voorkomt "alert fatigue": als elke kleine bevinding de pijplijn blokkeert, gaan teams op den duur waarschuwingen negeren of gates omzeilen.

4.3 Voorbeeld: GitHub Actions-workflow met meerdere security gates

Onderstaand voorbeeld toont een vereenvoudigde maar realistische GitHub Actions-workflow die statische analyse, dependency-scanning en secretsdetectie combineert, met een falende stap wanneer kritieke problemen worden gevonden.

GitHub Actions — devsecops-pipeline.yml
name: devsecops-pipeline

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up taal-runtime
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Installeer afhankelijkheden
        run: npm ci

      - name: Unit tests
        run: npm test -- --ci

  sast-scan:
    needs: build-and-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Semgrep SAST-scan
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/owasp-top-ten
            p/security-audit
        env:
          SEMGREP_RULES_FAIL_ON: "error"

  dependency-scan:
    needs: build-and-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Software Composition Analysis
        uses: aquasecurity/trivy-action@0.24.0
        with:
          scan-type: "fs"
          scan-ref: "."
          severity: "CRITICAL,HIGH"
          exit-code: "1"

  secrets-scan:
    needs: build-and-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Gitleaks secrets-scan
        uses: gitleaks/gitleaks-action@v2
        env:
          GITLEAKS_ENABLE_COMMENTS: "true"

  deploy:
    needs: [sast-scan, dependency-scan, secrets-scan]
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy naar productie
        run: ./scripts/deploy.sh production

4.4 Hetzelfde principe in GitLab CI

GitLab CI — .gitlab-ci.yml
stages:
  - build
  - security
  - deploy

variables:
  DOCKER_DRIVER: overlay2

build:
  stage: build
  script:
    - npm ci
    - npm run build

sast:
  stage: security
  image: returntocorp/semgrep
  script:
    - semgrep --config p/owasp-top-ten --error --config p/security-audit .
  allow_failure: false

dependency_scanning:
  stage: security
  image: aquasec/trivy:latest
  script:
    - trivy fs --severity CRITICAL,HIGH --exit-code 1 .
  allow_failure: false

secret_detection:
  stage: security
  image: zricethezav/gitleaks:latest
  script:
    - gitleaks detect --source . --exit-code 1

deploy_production:
  stage: deploy
  script:
    - ./scripts/deploy.sh production
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  needs:
    - sast
    - dependency_scanning
    - secret_detection
Let op

Zet security-jobs zoveel mogelijk parallel (zoals in beide voorbeelden) zodat ze de totale doorlooptijd van de pijplijn niet onnodig verlengen. Sequentiële scans die niet van elkaar afhankelijk zijn, zijn een veelgemaakte doorlooptijd-killer.

Hoofdstuk 5 — Threat modeling: nadenken vóór je bouwt

Threat modeling is het gestructureerd nadenken over wat er mis kan gaan met een systeem, vóórdat het gebouwd wordt — en het vervolgens ontwerpen van tegenmaatregelen. Het is een van de krachtigste shift-left-technieken, omdat het architecturale kwetsbaarheden aan het licht brengt die geen enkele scanner achteraf kan detecteren.

2026-07-06T09:32:23.133421 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 5.1 — Het threat modeling-proces en het STRIDE-raamwerk.

5.1 STRIDE: een praktisch raamwerk

STRIDE, ontwikkeld door Microsoft, is een van de meest gebruikte raamwerken voor het categoriseren van bedreigingen. Het is een ezelsbruggetje voor zes categorieën:

  • Spoofing — je voordoen als iemand of iets anders (bijvoorbeeld een vervalste identiteit of API-sleutel).
  • Tampering — het ongeautoriseerd wijzigen van data, in transit of at rest.
  • Repudiation — het kunnen ontkennen van een uitgevoerde actie, bij gebrek aan goede logging.
  • Information disclosure — het blootstellen van informatie aan onbevoegden.
  • Denial of service — het onbeschikbaar maken van een dienst.
  • Elevation of privilege — het verkrijgen van meer rechten dan toegestaan.

5.2 Het threat modeling-proces in vijf stappen

  1. Breng het systeem in kaart: teken een data flow diagram met componenten, datastromen en vertrouwensgrenzen (trust boundaries).
  2. Identificeer bedreigingen: loop voor elk onderdeel van het diagram de STRIDE-categorieën langs en stel de vraag "wat kan hier misgaan?".
  3. Beoordeel het risico: schat kans en impact in, bijvoorbeeld met een eenvoudige risicomatrix of het DREAD-model.
  4. Bepaal mitigaties: kies concrete tegenmaatregelen — technisch (encryptie, validatie, authenticatie) of procesmatig (code review, monitoring).
  5. Valideer en herhaal: threat modeling is geen eenmalige exercise; herhaal het bij elke significante architecturale wijziging.

5.3 Threat modeling integreren in DevSecOps

In een agile omgeving is een dagenlange threat modeling-sessie voor elke user story onrealistisch. Praktische aanpakken zijn: een lichte threat modeling-check als vast onderdeel van de Definition of Ready voor nieuwe features met significante architecturale impact, een jaarlijkse of per-kwartaal grondige herziening van het volledige systeem, en geautomatiseerde ondersteuning via tools die op basis van architectuurdiagrammen (bijvoorbeeld in code, zoals Threat Dragon of pytm) automatisch een deel van de bedreigingen suggereren.

pytm — declaratief threat model als Python-code
# Voorbeeld: threat model als code met pytm (Python)
from pytm import TM, Server, Datastore, Dataflow, Boundary, Actor

tm = TM("Voorbeeld: klantportaal")
tm.description = "Threat model van het klantportaal en de backend-API"

internet = Boundary("Internet")
interne_zone = Boundary("Interne zone")

klant = Actor("Klant")
klant.inBoundary = internet

webserver = Server("Webserver")
webserver.inBoundary = interne_zone
webserver.isEncrypted = True

database = Datastore("Klantendatabase")
database.inBoundary = interne_zone
database.isEncrypted = True

Dataflow(klant, webserver, "HTTPS-verzoek")
Dataflow(webserver, database, "SQL-query")

tm.process()

Hoofdstuk 6 — Secure coding practices

Geautomatiseerde scans zijn een vangnet, geen vervanging voor kennis. Ontwikkelaars die de belangrijkste kwetsbaarheidscategorieën begrijpen, schrijven vanaf het begin veiligere code en interpreteren scanresultaten beter.

6.1 De OWASP Top 10 als kompas

De OWASP Top 10 is een regelmatig bijgewerkte lijst van de meest voorkomende en impactvolle kwetsbaarheidscategorieën in webapplicaties. Ze vormt een uitstekend uitgangspunt voor training en voor het configureren van scanregels.

CategorieKorte omschrijvingVoorbeeldmaatregel
Broken access controlGebruikers kunnen acties uitvoeren of data inzien buiten hun rechtenServer-side autorisatiecontroles op elk endpoint
Cryptografische foutenGevoelige data onvoldoende of onjuist versleuteldTLS afdwingen, sterke, actuele algoritmen gebruiken
InjectionOngevalideerde invoer wordt geïnterpreteerd als code of queryParameterized queries, input-validatie, allowlisting
Onveilig ontwerpFundamentele ontwerpfouten, los van implementatieThreat modeling, secure design patterns
Verkeerde beveiligingsconfiguratieOnveilige standaardinstellingen, onnodige functies actiefHardening-baselines, configuratie als code
Kwetsbare en verouderde componentenGebruik van afhankelijkheden met bekende kwetsbaarhedenSCA-scanning, tijdig patchen
Identificatie- en authenticatiefoutenZwakke sessie- of wachtwoordafhandelingMulti-factor authenticatie, veilige sessietokens
Software- en data-integriteitsfoutenOnvoldoende verificatie van updates en CI/CD-pijplijnenOndertekende artefacten, geverifieerde pijplijnen
Tekortschietende logging en monitoringAanvallen blijven onopgemerkt door gebrekkige loggingGestructureerde logging, alerting op afwijkingen
Server-side request forgery (SSRF)Server wordt misbruikt om interne verzoeken te doenAllowlisting van uitgaande bestemmingen, netwerksegmentatie

6.2 Praktische secure coding-richtlijnen

  • Valideer alle invoer aan de serverzijde, ook als er al client-side validatie is — client-side controles zijn een gebruiksgemak, geen beveiligingsmaatregel.
  • Gebruik parameterized queries of ORM's in plaats van string-concatenatie voor databasequeries, om SQL-injectie te voorkomen.
  • Pas het principe van minimale rechten (least privilege) toe: elk proces, elke service-account en elke gebruiker krijgt precies genoeg rechten om zijn taak uit te voeren, niet meer.
  • Behandel alle externe invoer als onbetrouwbaar, inclusief data uit interne systemen en berichten van andere microservices.
  • Codeer output correct afhankelijk van de context (HTML, JavaScript, SQL) om cross-site scripting en injectie te voorkomen.
  • Vermijd het zelf bedenken van cryptografische algoritmen; gebruik beproefde, actief onderhouden bibliotheken.
  • Log beveiligingsrelevante gebeurtenissen (inlogpogingen, autorisatiefouten) zonder gevoelige data zoals wachtwoorden of volledige creditcardnummers te loggen.

6.3 Code review met een beveiligingsbril

Naast geautomatiseerde scans blijft menselijke code review waardevol, juist voor zaken die moeilijk automatisch te detecteren zijn: logische autorisatiefouten, onjuiste aannames over vertrouwde grenzen, en subtiele race conditions. Een korte securitychecklist als onderdeel van de pull request-template — bijvoorbeeld "is invoer gevalideerd?", "zijn nieuwe endpoints voorzien van autorisatiecontroles?", "worden er geen geheimen gelogd?" — verhoogt de kwaliteit van reviews aanzienlijk zonder veel overhead.

Hoofdstuk 7 — SAST en SCA: de eerste geautomatiseerde verdedigingslinie

7.1 Static Application Security Testing (SAST)

SAST-tools analyseren broncode, bytecode of binaries zonder de applicatie uit te voeren. Ze bouwen een model van de code (vaak een abstracte syntaxboom of controlestroomgraaf) en zoeken naar patronen die met bekende kwetsbaarheidscategorieën overeenkomen, zoals onveilige functieaanroepen, ontbrekende invoervalidatie of hardcoded geheimen.

Bekende open source en commerciële SAST-tools zijn onder meer Semgrep, SonarQube, CodeQL en Checkmarx. Semgrep is populair vanwege de leesbare, YAML-gebaseerde regelsyntaxis, waarmee teams eenvoudig eigen regels kunnen schrijven naast de kant-en-klare regelsets.

Semgrep — custom-rule.yml
# Voorbeeld: eigen Semgrep-regel om hardcoded wachtwoorden te detecteren
rules:
  - id: hardcoded-wachtwoord
    languages: [python]
    message: >
      Mogelijk hardcoded wachtwoord gevonden. Gebruik een secrets-manager
      of omgevingsvariabele in plaats van een letterlijke waarde in de code.
    severity: ERROR
    metadata:
      category: security
      owasp: "A07:2021 - Identification and Authentication Failures"
    patterns:
      - pattern-either:
          - pattern: $VAR = "..."
      - metavariable-regex:
          metavariable: $VAR
          regex: (?i)(password|wachtwoord|secret|token|apikey)

7.2 SAST-configuratie in de pijplijn

GitHub Actions — codeql-analysis.yml
# GitHub Actions job: SAST met CodeQL
name: codeql-analysis

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 3 * * 1"   # wekelijkse volledige scan

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    strategy:
      matrix:
        language: ["javascript", "python"]
    steps:
      - uses: actions/checkout@v4

      - name: Initialiseer CodeQL
        uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          queries: security-extended

      - name: Autobuild
        uses: github/codeql-action/autobuild@v3

      - name: Voer CodeQL-analyse uit
        uses: github/codeql-action/analyze@v3

7.3 Software Composition Analysis (SCA)

Moderne applicaties bestaan voor een groot deel — vaak meer dan tachtig procent — uit open source afhankelijkheden. SCA-tools analyseren deze afhankelijkheden, vergelijken ze met databases van bekende kwetsbaarheden (zoals de National Vulnerability Database) en signaleren wanneer een gebruikte versie een bekend beveiligingsprobleem bevat. Populaire tools zijn Trivy, Grype, Snyk en OWASP Dependency-Check.

GitLab CI — dependency-scanning met SBOM
# GitLab CI: SCA met Trivy, met SBOM-generatie
dependency_scanning:
  stage: security
  image: aquasec/trivy:latest
  variables:
    TRIVY_CACHE_DIR: ".trivycache"
  script:
    - trivy fs --format table --severity CRITICAL,HIGH,MEDIUM .
    - trivy fs --format cyclonedx --output sbom.json .
    - trivy fs --severity CRITICAL,HIGH --exit-code 1 .
  artifacts:
    paths:
      - sbom.json
    reports:
      dependency_scanning: sbom.json
  cache:
    paths:
      - .trivycache/

7.4 Omgaan met valse positieven en "noise"

Een veelgehoorde klacht over SAST- en SCA-tools is het aantal valse positieven: bevindingen die bij nadere inspectie geen daadwerkelijk risico vormen. Dit ondermijnt het vertrouwen van ontwikkelaars in de tooling. Praktische aanpakken om dit te beperken zijn: het afstemmen van regelsets op de gebruikte taal en context in plaats van alle standaardregels te activeren, het gebruik van een baseline zodat alleen nieuwe bevindingen worden getoond, en het documenteren van bewust geaccepteerde bevindingen (met motivatie en vervaldatum) in plaats van ze te negeren.

Praktijktip

Voer bij de introductie van een nieuwe scanner eerst een 'baseline-scan' uit op de bestaande codebase, en configureer de pijplijn zodat alleen nieuwe bevindingen (ten opzichte van deze baseline) de build blokkeren. Dit voorkomt dat een team wordt overspoeld door duizenden historische bevindingen op dag één.

Hoofdstuk 8 — DAST: de applicatie testen terwijl hij draait

Waar SAST naar de broncode kijkt, test Dynamic Application Security Testing (DAST) een daadwerkelijk draaiende applicatie, meestal in een staging- of testomgeving. DAST-tools gedragen zich als een geautomatiseerde aanvaller: ze sturen verzoeken naar de applicatie, manipuleren invoer en analyseren de respons op tekenen van kwetsbaarheden zoals SQL-injectie, cross-site scripting of onjuiste beveiligingsheaders.

8.1 SAST versus DAST versus IAST

TypeWat wordt getestVoordeelBeperking
SASTBroncode, zonder uitvoeringVroeg in de cyclus, exacte locatie in codeGeen zicht op runtime-configuratie
DASTDraaiende applicatie, van buitenafVindt runtime- en configuratiefoutenLater in de cyclus, geen exacte coderegel
IASTApplicatie tijdens tests, met interne instrumentatieCombineert snelheid met detailVereist instrumentatie van de applicatie

8.2 DAST integreren in de pijplijn met OWASP ZAP

OWASP ZAP (Zed Attack Proxy) is een van de meest gebruikte open source DAST-tools. Het kan als geautomatiseerde baseline-scan of als volledige actieve scan tegen een staging-omgeving worden ingezet.

GitHub Actions — dast-scan.yml
# GitHub Actions: DAST-scan met OWASP ZAP tegen een staging-omgeving
name: dast-scan

on:
  workflow_run:
    workflows: ["deploy-staging"]
    types: [completed]

jobs:
  zap-scan:
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    runs-on: ubuntu-latest
    steps:
      - name: OWASP ZAP baseline scan
        uses: zaproxy/action-baseline@v0.12.0
        with:
          target: "https://staging.voorbeeld-app.nl"
          rules_file_name: ".zap/rules.tsv"
          cmd_options: "-a"
          fail_action: true

      - name: Publiceer rapport als artefact
        uses: actions/upload-artifact@v4
        with:
          name: zap-rapport
          path: report_html.html
.zap/rules.tsv — voorbeeldregels
# .zap/rules.tsv - regels om bepaalde bevindingen te negeren of te downgraden
# formaat: <rule-id> <actie: IGNORE|WARN|FAIL> <toelichting>
10021	WARN	X-Content-Type-Options ontbreekt op statische assets
10038	FAIL	Content Security Policy header ontbreekt of te permissief
90022	IGNORE	Bekende false positive op health-check endpoint

8.3 Wanneer DAST wel en niet zinvol is

DAST is bijzonder waardevol voor het vinden van configuratiefouten die pas zichtbaar worden wanneer een applicatie daadwerkelijk draait: ontbrekende beveiligingsheaders, onjuist ingestelde TLS, of endpoints die per ongeluk publiek toegankelijk zijn. Het is minder geschikt voor het vinden van logische autorisatiefouten die specifieke, geauthenticeerde gebruikersscenario's vereisen — daarvoor zijn gerichte, op maat geschreven testscripts of handmatige penetratietests beter geschikt. DAST vervangt periodieke, diepgaande penetratietests dan ook niet, maar vult ze aan door continu een brede, ondiepe controle uit te voeren.

Hoofdstuk 9 — Infrastructure as Code en containerbeveiliging

Met de opkomst van cloud-native architecturen is infrastructuur zelf code geworden: Terraform, CloudFormation, Kubernetes-manifests en Helm-charts beschrijven declaratief hoe een omgeving eruitziet. Dit betekent dat dezelfde principes die gelden voor applicatiecode — versiebeheer, code review, geautomatiseerde tests — ook op infrastructuur van toepassing zijn. Het betekent ook dat fouten in infrastructuurcode net zo'n groot beveiligingsrisico vormen als fouten in applicatiecode, met als extra risico dat ze vaak breder impact hebben.

9.1 Infrastructure as Code (IaC) scanning

IaC-scanners analyseren configuratiebestanden op bekende misconfiguraties: publiek toegankelijke opslag, ontbrekende encryptie, te ruime firewallregels, of containers die als root draaien. Bekende tools zijn tfsec, Checkov en Terrascan.

Terraform — voorbeeld met misconfiguratie
# Terraform-fragment MET een veelvoorkomende misconfiguratie
resource "aws_s3_bucket" "data" {
  bucket = "voorbeeld-klantdata"
}

resource "aws_s3_bucket_public_access_block" "data" {
  bucket                  = aws_s3_bucket.data.id
  block_public_acls       = false   # <-- kwetsbaarheid: publieke ACL's toegestaan
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}
GitLab CI — iac-scan.yml
# GitLab CI: IaC-scan met tfsec en Checkov
iac_scan:
  stage: security
  image:
    name: aquasec/tfsec:latest
    entrypoint: [""]
  script:
    - tfsec ./infrastructure --minimum-severity HIGH --format default
  rules:
    - changes:
        - infrastructure/**/*.tf

checkov_scan:
  stage: security
  image: bridgecrew/checkov:latest
  script:
    - checkov -d ./infrastructure --framework terraform --compact --quiet
  rules:
    - changes:
        - infrastructure/**/*.tf

9.2 Containerbeveiliging in lagen

Containers introduceren een eigen verzameling risico's: kwetsbare basis-images, containers die met te veel rechten draaien, en een gedeelde kernel die een aanvaller mogelijk kan gebruiken om van een container naar de host te ontsnappen (container escape). Containerbeveiliging vereist daarom een gelaagde aanpak.

2026-07-06T09:32:23.271611 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 9.1 — Verdediging in lagen voor containers: van infrastructuur tot applicatiecode.

9.3 Container image scanning

GitHub Actions — container image scan
# GitHub Actions: image scanning met Trivy vóór het pushen naar de registry
jobs:
  build-and-scan-image:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Bouw container-image
        run: docker build -t registry.voorbeeld.nl/app:${{ github.sha }} .

      - name: Scan image met Trivy
        uses: aquasecurity/trivy-action@0.24.0
        with:
          image-ref: "registry.voorbeeld.nl/app:${{ github.sha }}"
          severity: "CRITICAL,HIGH"
          exit-code: "1"
          ignore-unfixed: true
          format: "table"

      - name: Push naar registry (alleen bij geslaagde scan)
        run: docker push registry.voorbeeld.nl/app:${{ github.sha }}

9.4 Kubernetes hardening

Een correct geconfigureerd Kubernetes-cluster beperkt de impact van een gecompromitteerde container aanzienlijk. Belangrijke maatregelen zijn: containers nooit als root laten draaien, een read-only root filesystem waar mogelijk, expliciete resource-limieten, netwerkbeleid (NetworkPolicy) dat verkeer tussen pods beperkt tot wat noodzakelijk is, en admission controllers die onveilige manifests blokkeren vóórdat ze worden toegepast.

Kubernetes — gehardend pod-manifest
# Kubernetes: veilig geconfigureerd Pod-manifest
apiVersion: v1
kind: Pod
metadata:
  name: voorbeeld-app
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 10001
    fsGroup: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: registry.voorbeeld.nl/app:1.4.2
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
      resources:
        limits:
          cpu: "500m"
          memory: "256Mi"
        requests:
          cpu: "100m"
          memory: "128Mi"
      ports:
        - containerPort: 8080
Kubernetes — NetworkPolicy
# Kubernetes: NetworkPolicy die verkeer beperkt tot het noodzakelijke
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-netwerkbeleid
spec:
  podSelector:
    matchLabels:
      app: voorbeeld-app
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api-gateway
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - protocol: TCP
          port: 5432
Praktijktip

Gebruik zo klein mogelijke basis-images (distroless of Alpine-varianten) om het aanvalsoppervlak te beperken: hoe minder software in het image, hoe minder er kwetsbaar kan zijn en hoe kleiner de image om te scannen en te distribueren.

Hoofdstuk 10 — Secretsbeheer

Wachtwoorden, API-sleutels, certificaten en tokens — samen "secrets" genoemd — zijn een van de meest voorkomende oorzaken van datalekken wanneer ze per ongeluk in broncode, configuratiebestanden of logs terechtkomen. Secretsbeheer is het geheel van praktijken en tooling om deze gevoelige waarden veilig op te slaan, te distribueren en te roteren.

10.1 Waarom secrets niet in code horen

Zodra een geheim in een Git-repository wordt gecommit, blijft het — ook na verwijdering — in de geschiedenis staan, tenzij de volledige geschiedenis wordt herschreven. Bovendien worden repositories vaak gekopieerd, geforkt of gedeeld, waardoor een eenmaal gelekt geheim moeilijk terug te trekken is. De enige betrouwbare oplossing is: secrets nooit committen, en als het toch gebeurt, het geheim onmiddellijk intrekken (roteren) — het verwijderen uit de geschiedenis alleen is onvoldoende.

10.2 Geautomatiseerde secretsdetectie

Tools als Gitleaks en TruffleHog scannen commits op patronen die kenmerkend zijn voor geheimen (API-sleutels, private keys, tokens) en kunnen worden ingezet als pre-commit hook (lokaal, vóórdat een commit wordt gemaakt) én als pijplijnstap (als laatste vangnet).

.pre-commit-config.yaml
# .pre-commit-config.yaml - lokale controle vóór elke commit
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.4
    hooks:
      - id: gitleaks

  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: detect-private-key
      - id: check-added-large-files

10.3 Centrale secrets-managers

In plaats van geheimen te verspreiden over configuratiebestanden, omgevingsvariabelen en scripts, worden ze idealiter centraal beheerd in een secrets-manager zoals HashiCorp Vault, AWS Secrets Manager, Azure Key Vault of Google Secret Manager. Applicaties en pijplijnen vragen geheimen dynamisch op via een API, met fijnmazige toegangscontrole, audit-logging en automatische rotatie.

GitHub Actions — secrets ophalen uit Vault
# GitHub Actions: secrets ophalen uit HashiCorp Vault tijdens de pijplijn
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Haal secrets op uit Vault
        uses: hashicorp/vault-action@v3
        with:
          url: https://vault.voorbeeld.nl
          method: jwt
          role: ci-deploy-role
          secrets: |
            secret/data/productie/database DB_WACHTWOORD | DB_PASSWORD ;
            secret/data/productie/api API_SLEUTEL | API_KEY

      - name: Deploy met opgehaalde secrets
        run: ./scripts/deploy.sh
        env:
          DB_PASSWORD: ${{ env.DB_PASSWORD }}
          API_KEY: ${{ env.API_KEY }}

10.4 Kubernetes secrets: standaard onvoldoende

Standaard Kubernetes Secrets worden slechts base64-gecodeerd, niet versleuteld — dit is geen beveiligingsmaatregel maar enkel een encoderingsformaat. Voor productieomgevingen wordt daarom aangeraden encryptie-at-rest voor de etcd-datastore te activeren en, waar mogelijk, een externe secrets-manager te integreren met tools zoals External Secrets Operator, die geheimen dynamisch synchroniseert vanuit Vault of een cloud-provider naar Kubernetes.

Kubernetes — ExternalSecret
# External Secrets Operator: synchroniseer een secret vanuit Vault naar Kubernetes
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: database-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: database-credentials
    creationPolicy: Owner
  data:
    - secretKey: password
      remoteRef:
        key: secret/data/productie/database
        property: DB_WACHTWOORD
Praktijktip

Behandel elk gelekt geheim als gecompromitteerd, ongeacht hoe kort het zichtbaar was. Automatiseer rotatie zodat een lek een routinematige, snelle actie wordt in plaats van een crisis.

Hoofdstuk 11 — Policy as Code en compliance as code

Naarmate organisaties groeien, groeit ook de behoefte om organisatiebeleid — bijvoorbeeld "containers mogen nooit als root draaien" of "opslag moet altijd versleuteld zijn" — consistent af te dwingen over honderden of duizenden repositories en clusters. Handmatige controle is dan niet meer haalbaar. Policy as code maakt het mogelijk om dit beleid te definiëren als machineleesbare regels die automatisch worden afgedwongen.

11.1 Open Policy Agent (OPA) en Rego

Open Policy Agent is een veelgebruikte, cloud-native policy-engine. Beleid wordt geschreven in de taal Rego en kan worden toegepast op uiteenlopende contexten: Kubernetes-admission control, API-autorisatie, of validatie van Terraform-plannen.

Rego — pod-security-policy.rego
# Rego-beleid: verbied containers die als root draaien
package kubernetes.admission

deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  not container.securityContext.runAsNonRoot
  msg := sprintf(
    "Container '%v' moet runAsNonRoot: true instellen",
    [container.name]
  )
}

deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  container.securityContext.privileged == true
  msg := sprintf(
    "Container '%v' mag niet in privileged-modus draaien",
    [container.name]
  )
}

11.2 OPA Gatekeeper: afdwinging in Kubernetes

OPA Gatekeeper — ConstraintTemplate en Constraint
# ConstraintTemplate: definieert een herbruikbare regel
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequirenonroot
spec:
  crd:
    spec:
      names:
        kind: K8sRequireNonRoot
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequirenonroot
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsNonRoot
          msg := sprintf("Container %v moet runAsNonRoot instellen", [container.name])
        }
---
# Constraint: past de regel toe op alle Pods in het cluster
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequireNonRoot
metadata:
  name: vereis-non-root-containers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]

11.3 Policy as code in de pijplijn: Terraform-validatie

GitLab CI — policy-validatie met Conftest
# GitLab CI: Terraform-plan valideren tegen OPA-beleid vóór apply
policy_check:
  stage: security
  image: openpolicyagent/conftest:latest
  script:
    - terraform plan -out=tfplan.binary
    - terraform show -json tfplan.binary > tfplan.json
    - conftest test tfplan.json --policy ./policies
  rules:
    - changes:
        - infrastructure/**/*.tf

11.4 Compliance as code

Voor organisaties die moeten voldoen aan raamwerken zoals ISO 27001, SOC 2, NIS2 of sectorspecifieke regelgeving, biedt compliance as code een manier om nalevingseisen te vertalen naar geautomatiseerde, continu gecontroleerde regels, in plaats van jaarlijkse, handmatige audits. Tools zoals Chef InSpec of Open Policy Agent kunnen infrastructuur en configuraties continu toetsen aan compliance-baselines, en de resultaten dienen als doorlopend bewijs ("continuous compliance") in plaats van een momentopname.

InSpec — ssh_hardening.rb
# InSpec-controle: vereis dat SSH-wachtwoordauthenticatie is uitgeschakeld
control 'ssh-01' do
  impact 1.0
  title 'SSH-wachtwoordauthenticatie moet uitgeschakeld zijn'
  desc 'Alleen sleutelgebaseerde authenticatie is toegestaan volgens het hardeningsbeleid.'
  describe sshd_config do
    its('PasswordAuthentication') { should cmp 'no' }
  end
end
Praktijktip

Begin met policy as code op een klein aantal, hoog-risico regels (bijvoorbeeld 'geen publieke opslag' en 'geen root-containers') en breid geleidelijk uit. Een overweldigende hoeveelheid regels bij de start leidt tot weerstand en workarounds.

Hoofdstuk 12 — Monitoring, logging en incident response

Zelfs de meest volwassen DevSecOps-praktijk kan niet elk incident voorkomen. Shield right — het bewaken van systemen ná deployment — is daarom net zo essentieel als shift left. Dit hoofdstuk behandelt runtime-monitoring, logging en een gestructureerde aanpak van incident response.

12.1 Wat runtime-beveiliging toevoegt

Statische en pre-deployment scans kunnen niet alles vangen: zero-day kwetsbaarheden, aanvallen die misbruik maken van legitiem gedrag, en configuratiedrift die na verloop van tijd ontstaat. Runtime-beveiligingstools monitoren het daadwerkelijke gedrag van applicaties en infrastructuur, en signaleren afwijkingen zoals ongebruikelijke netwerkverbindingen, onverwachte procesuitvoering binnen een container, of pogingen tot privilege-escalatie.

Falco — runtime-detectieregel
# Falco: runtime-detectieregel voor ongebruikelijke shell-activiteit in een container
- rule: Onverwachte shell in productiecontainer
  desc: Detecteert het starten van een interactieve shell binnen een productiecontainer
  condition: >
    spawned_process and container and
    container.image.repository contains "voorbeeld-app" and
    proc.name in (bash, sh, zsh) and
    not proc.pname in (entrypoint.sh, supervisord)
  output: >
    Onverwachte shell gestart in container
    (container=%container.name image=%container.image.repository
    process=%proc.name gebruiker=%user.name commandline=%proc.cmdline)
  priority: WARNING
  tags: [container, shell, runtime]

12.2 Gestructureerde logging als basisvoorwaarde

Effectieve detectie begint bij goede logging. Applicaties moeten beveiligingsrelevante gebeurtenissen — inlogpogingen, autorisatiefouten, wijzigingen aan gevoelige gegevens, beheerdershandelingen — vastleggen in een gestructureerd formaat (bijvoorbeeld JSON), voorzien van consistente velden zoals tijdstip, gebruikers-ID, bron-IP en actie. Dit maakt het mogelijk om logs centraal te verzamelen, te doorzoeken en te correleren met tools zoals de ELK-stack, Grafana Loki of een SIEM-platform.

Voorbeeld — gestructureerd beveiligingslogbericht (JSON)
{
  "tijdstip": "2026-03-14T09:22:11Z",
  "gebeurtenis": "authenticatie_mislukt",
  "gebruiker_id": "onbekend",
  "poging_gebruikersnaam": "admin",
  "bron_ip": "203.0.113.42",
  "applicatie": "klantportaal-api",
  "aantal_pogingen_laatste_uur": 27,
  "ernst": "hoog"
}

12.3 Alerting zonder alert fatigue

Een veelgemaakte fout is het genereren van te veel waarschuwingen, waardoor teams ze op den duur negeren. Effectieve alerting is gebaseerd op een duidelijke prioritering: kritieke alerts die direct menselijke actie vereisen (bijvoorbeeld actief misbruik), waarschuwingen die in een dashboard verschijnen voor periodieke review, en informatieve gebeurtenissen die alleen worden gelogd. Alerts moeten bovendien actiegericht zijn: elke alert zou een duidelijk antwoord moeten hebben op de vraag "wat moet ik nu doen?".

12.4 Incident response: een gestructureerde aanpak

Wanneer een incident zich voordoet, bepaalt de kwaliteit van de voorbereiding hoe snel en effectief een organisatie reageert. Een veelgebruikt raamwerk, gebaseerd op NIST-richtlijnen, onderscheidt zes fasen.

2026-07-06T09:32:23.691154 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 12.1 — De incident response-cyclus.
  • Voorbereiden: draaiboeken (runbooks), contactlijsten, tooling en trainingsoefeningen zijn vooraf op orde.
  • Detecteren en analyseren: het incident wordt herkend, geclassificeerd naar ernst en de omvang wordt in kaart gebracht.
  • Indammen (containment): de directe schade wordt beperkt, bijvoorbeeld door getroffen systemen te isoleren.
  • Uitroeien (eradication): de onderliggende oorzaak wordt weggenomen, bijvoorbeeld door een kwetsbaarheid te patchen of een gecompromitteerd account te blokkeren.
  • Herstellen (recovery): systemen worden veilig teruggebracht naar normale werking, met verhoogde monitoring.
  • Lessen trekken (post-mortem): een blameless evaluatie van wat er is gebeurd, wat goed ging, en welke verbeteringen nodig zijn.

12.5 Runbooks als code

Net als infrastructuur en beleid kunnen ook incidentresponsprocedures worden vastgelegd als code of gestructureerde configuratie, zodat ze consistent en (deels) geautomatiseerd kunnen worden uitgevoerd, bijvoorbeeld het automatisch isoleren van een gecompromitteerde pod.

Kubernetes — automatische quarantaine-policy (sjabloon)
# Voorbeeld: geautomatiseerde respons op een Falco-alert via een webhook naar Kubernetes
# Bij een kritieke alert wordt de betreffende pod automatisch geïsoleerd
# door een NetworkPolicy toe te passen die al het verkeer blokkeert.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: quarantaine-{{ POD_NAME }}
  labels:
    reden: automatische-incidentrespons
spec:
  podSelector:
    matchLabels:
      app: "{{ POD_APP_LABEL }}"
  policyTypes:
    - Ingress
    - Egress
  ingress: []
  egress: []
Praktijktip

Oefen incident response net zoals een brandoefening: met periodieke, aangekondigde en onaangekondigde simulaties ("game days"). Een draaiboek dat nooit is getest, faalt vaak precies op het moment dat het nodig is.

Hoofdstuk 13 — Security metrics en KPI's

Wat niet gemeten wordt, kan niet systematisch verbeterd worden. Tegelijk is het een valkuil om te veel of de verkeerde metrics bij te houden: metrics die niet tot actie leiden, zijn ruis. Dit hoofdstuk beschrijft welke metrics waardevol zijn en hoe ze te interpreteren.

2026-07-06T09:32:23.583786 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 13.1 — De meetfunnel: van ruwe scanresultaten naar daadwerkelijk opgeloste risico's.

13.1 Belangrijke metrics

MetricWat het meetWaarom het waardevol is
Mean Time To Remediate (MTTR)Gemiddelde tijd tussen ontdekking en oplossing van een kwetsbaarheidToont hoe snel een team daadwerkelijk risico's wegneemt
Aantal kritieke bevindingen openActuele hoeveelheid onopgeloste kritieke risico'sDirecte indicatie van blootstelling aan risico
Dekkingsgraad van scansPercentage repositories/pijplijnen met actieve security-scansSignaleert blinde vlekken in de organisatie
% builds geblokkeerd door security gateHoe vaak een gate daadwerkelijk ingrijptTe hoog percentage kan wijzen op te strenge regels of onderliggende problemen
Herhaling van bevindingenHoe vaak dezelfde soort fout terugkeertSignaal voor structurele training of tooling-behoefte
Tijd tot patch bij nieuwe CVESnelheid van reactie op nieuw ontdekte kwetsbaarheden in afhankelijkhedenBelangrijk bij snel geëxploiteerde kwetsbaarheden

13.2 Metrics gebruiken zonder perverse prikkels

Metrics kunnen ongewenst gedrag stimuleren als ze verkeerd worden ingezet. Als teams bijvoorbeeld alleen worden afgerekend op "aantal open bevindingen", ontstaat de prikkel om bevindingen te sluiten zonder ze daadwerkelijk op te lossen (bijvoorbeeld door ze te onderdrukken of als "acceptabel risico" te markeren zonder degelijke onderbouwing). Effectieve metrics worden daarom altijd in combinatie gebruikt, en het doel is trendverbetering over tijd, niet het behalen van een absoluut getal.

13.3 Dashboards en rapportage

Een goed dashboard toont metrics op het juiste detailniveau voor het juiste publiek: een team wil per repository en per sprint bevindingen zien, terwijl management een geaggregeerd, organisatiebreed beeld nodig heeft over trends en risicogebieden. Veel scanners kunnen resultaten exporteren naar gestandaardiseerde formaten zoals SARIF, die vervolgens centraal kunnen worden samengevoegd en gevisualiseerd.

GitHub Actions — SARIF-upload
# GitHub Actions: SARIF-resultaten uploaden naar de Security-tab
- name: Upload SARIF-resultaten
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: resultaten.sarif
    category: sast-semgrep

Hoofdstuk 14 — Software supply chain security

De afgelopen jaren hebben verschillende geruchtmakende incidenten aangetoond dat aanvallers zich niet alleen richten op de applicatie zelf, maar ook op de keten eromheen: gecompromitteerde build-servers, vervalste pakketten in publieke registries, en kwaadaardige wijzigingen in veelgebruikte open source projecten. Supply chain security richt zich op het beveiligen van deze volledige keten, van broncode tot uitgerold artefact.

2026-07-06T09:32:23.388516 image/svg+xml Matplotlib v3.10.8, https://matplotlib.org/
Figuur 14.1 — De software supply chain: van broncode tot geverifieerd, ondertekend artefact.

14.1 Software Bill of Materials (SBOM)

Een SBOM is een gestructureerde lijst van alle componenten waaruit een softwareproduct is opgebouwd, inclusief versies en licenties. Het is te vergelijken met een ingrediëntenlijst: wanneer een nieuwe kwetsbaarheid wordt ontdekt in een veelgebruikte bibliotheek, maakt een actuele SBOM het mogelijk om binnen minuten te bepalen welke systemen zijn geraakt, in plaats van dagenlang handmatig uit te zoeken. De twee meest gebruikte standaarden zijn SPDX en CycloneDX.

GitHub Actions — sbom-generatie.yml
# GitHub Actions: SBOM genereren en als artefact bewaren bij elke release
generate-sbom:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Genereer SBOM met Syft
      uses: anchore/sbom-action@v0.17.0
      with:
        format: cyclonedx-json
        output-file: sbom.cyclonedx.json

    - name: Bewaar SBOM als release-artefact
      uses: actions/upload-artifact@v4
      with:
        name: sbom
        path: sbom.cyclonedx.json

14.2 Artefacten ondertekenen en verifiëren

Het ondertekenen van build-artefacten (container-images, pakketten, binaries) maakt het mogelijk om cryptografisch te verifiëren dat een artefact daadwerkelijk afkomstig is van de verwachte, vertrouwde build-pijplijn en niet onderweg is gemanipuleerd. Sigstore, met de tool Cosign, heeft dit proces sterk vereenvoudigd door keyless signing te introduceren, gebaseerd op korte-levensduur certificaten in plaats van langlopende privésleutels die apart beheerd moeten worden.

GitHub Actions — image ondertekenen en verifiëren met Cosign
# GitHub Actions: container-image ondertekenen met Cosign (keyless signing)
sign-image:
  runs-on: ubuntu-latest
  permissions:
    id-token: write
    contents: read
  steps:
    - uses: actions/checkout@v4

    - name: Installeer Cosign
      uses: sigstore/cosign-installer@v3

    - name: Onderteken image
      run: |
        cosign sign --yes 
          registry.voorbeeld.nl/app@${{ steps.build.outputs.digest }}

    - name: Verifieer handtekening (voorbeeld bij deployment)
      run: |
        cosign verify 
          --certificate-identity-regexp "https://github.com/voorbeeld-org/.*" 
          --certificate-oidc-issuer "https://token.actions.githubusercontent.com" 
          registry.voorbeeld.nl/app@${{ steps.build.outputs.digest }}

14.3 SLSA: een raamwerk voor build-integriteit

SLSA (Supply-chain Levels for Software Artifacts) is een raamwerk dat oplopende niveaus van zekerheid definieert over hoe een artefact is gebouwd: van basale herleidbaarheid tot volledig geïsoleerde, reproduceerbare builds met cryptografisch geverifieerde herkomst (provenance). Het biedt organisaties een gemeenschappelijke taal en groeipad om supply chain-risico's stap voor stap te verminderen, in plaats van in één keer een onhaalbaar hoog niveau na te streven.

14.4 Afhankelijkheden van vertrouwde bronnen

  • Gebruik private package-registries of proxy's (bijvoorbeeld Artifactory of Nexus) die pakketten cachen en scannen vóórdat ze intern beschikbaar komen.
  • Pin afhankelijkheden op exacte versies of cryptografische hashes in plaats van losse versiebereiken, om onverwachte, ongecontroleerde updates te voorkomen.
  • Controleer periodiek op typosquatting: kwaadaardige pakketten met namen die sterk lijken op populaire, legitieme pakketten.
  • Beperk wie build-pijplijnen kan wijzigen, aangezien een gecompromitteerde pijplijn de facto een compromittering van elk uitgeleverd artefact betekent.
Praktijktip

Behandel de CI/CD-pijplijn zelf als een kritiek productiesysteem: met eigen toegangscontrole, monitoring en threat modeling. Een aanvaller die de pijplijn beheerst, hoeft de applicatie zelf niet meer aan te vallen.

Hoofdstuk 15 — Organisatie en cultuurverandering

De technische onderdelen van DevSecOps — scanners, pijplijnen, policy-engines — zijn relatief eenvoudig aan te schaffen. De werkelijke uitdaging zit in de organisatorische en culturele verandering die nodig is om deze tooling effectief te laten werken. Dit hoofdstuk bespreekt hoe organisaties deze transitie stapsgewijs kunnen doorvoeren.

15.1 Volwassenheidsmodellen

Volwassenheidsmodellen, zoals het OWASP Software Assurance Maturity Model (SAMM) of het DevSecOps Maturity Model (DSOMM), helpen organisaties objectief te bepalen waar ze staan en wat logische vervolgstappen zijn. In plaats van een vaag gevoel van "we doen al wel iets aan security", bieden deze modellen concrete niveaus per praktijkgebied (bijvoorbeeld threat modeling, testen, incident response), zodat verbetering meetbaar en gericht kan plaatsvinden.

VolwassenheidsniveauKenmerken
Niveau 1 — Ad hocBeveiliging is reactief; scans (indien aanwezig) worden handmatig en incidenteel uitgevoerd.
Niveau 2 — HerhaalbaarBasale scans zijn geautomatiseerd in de pijplijn; beleid bestaat maar wordt niet overal afgedwongen.
Niveau 3 — GedefinieerdSecurity gates zijn standaard; security champions zijn actief; metrics worden bijgehouden.
Niveau 4 — BeheerstPolicy as code wordt organisatiebreed afgedwongen; threat modeling is gestandaardiseerd; supply chain-maatregelen zijn actief.
Niveau 5 — OptimaliserendContinue verbetering op basis van metrics en incidenten; security is volledig verweven in de ontwikkelcultuur.

15.2 Begin klein, schaal bewust

Een veelgemaakte fout is het in één keer uitrollen van uitgebreide tooling en strenge policy's over de hele organisatie. Dit leidt tot weerstand, overbelaste teams en workarounds die de beveiliging juist ondermijnen. Een effectievere aanpak is het starten met een pilotteam, het aantonen van waarde met concrete resultaten, en het geleidelijk uitbreiden naar andere teams — waarbij lessen uit de pilot worden meegenomen.

15.3 Training en bewustwording

Geautomatiseerde tooling is geen vervanging voor kennis. Structurele investering in training — secure coding-workshops, threat modeling-sessies, capture-the-flag-oefeningen — verhoogt de kwaliteit van code vóórdat deze ooit een scanner bereikt. Training is het meest effectief wanneer die relevant en praktisch is: voorbeelden uit de eigen codebase werken beter dan generieke, abstracte lessen.

15.4 Samenwerking tussen teams

Structurele overlegvormen — zoals een terugkerend security-guild overleg, waarin security champions van verschillende teams kennis en ervaringen uitwisselen — houden beveiliging zichtbaar en actueel. Het security-team kan hierin een coachende rol spelen: niet als poortwachter die goedkeuring geeft, maar als expert die teams helpt zelfstandig goede beslissingen te nemen.

15.5 Leiderschap en draagvlak

Zonder zichtbare steun van management blijft DevSecOps een geïsoleerd initiatief van een handvol enthousiaste engineers. Leiderschap moet niet alleen middelen beschikbaar stellen, maar ook expliciet ruimte geven om kwaliteit boven puur leveringstempo te stellen wanneer dat nodig is — bijvoorbeeld door te accepteren dat een release wordt uitgesteld wanneer een kritieke kwetsbaarheid wordt gevonden.

Praktijktip

Vier zichtbare successen, hoe klein ook: het aantal kritieke bevindingen dat is opgelost, een team dat zijn eerste threat model heeft afgerond, of een incident dat dankzij monitoring vroegtijdig werd ontdekt. Zichtbare erkenning versterkt de gewenste cultuur sterker dan beleidsdocumenten.

Hoofdstuk 16 — Praktijkcasus: een volledige DevSecOps-pijplijn

In dit hoofdstuk brengen we de eerdere hoofdstukken samen in één doorlopend voorbeeld: een fictieve organisatie, "Voorbeeld B.V.", die een klantportaal bouwt en uitrolt op Kubernetes. We doorlopen de volledige pijplijn, van commit tot productie, met alle besproken security gates geïntegreerd.

16.1 De architectuur

Het klantportaal bestaat uit een front-end, een backend-API, een PostgreSQL-database en draait als containers op een Kubernetes-cluster in de cloud. Code wordt beheerd in Git, en elke wijziging doorloopt de onderstaande pijplijn vóór deze in productie komt.

16.2 De volledige pijplijnconfiguratie

Onderstaande GitHub Actions-workflow combineert alle eerder besproken controles in een samenhangend geheel: bouwen en testen, statische analyse, dependency-scanning, secretsdetectie, container image-scanning, IaC-validatie, ondertekening van het artefact, en tot slot een DAST-scan tegen de staging-omgeving vóórdat een handmatige goedkeuring de productie-deployment vrijgeeft.

GitHub Actions — volledige pijplijn voor Voorbeeld B.V.
name: voorbeeld-bv-devsecops-pipeline

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

permissions:
  contents: read
  security-events: write
  id-token: write

jobs:
  # ---------- FASE 1: Bouwen en unit-testen ----------
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: "20" }
      - run: npm ci
      - run: npm test -- --ci

  # ---------- FASE 2: Statische analyse (parallel) ----------
  sast:
    needs: build-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: returntocorp/semgrep-action@v1
        with:
          config: p/owasp-top-ten p/security-audit

  dependency-scan:
    needs: build-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aquasecurity/trivy-action@0.24.0
        with:
          scan-type: "fs"
          severity: "CRITICAL,HIGH"
          exit-code: "1"

  secrets-scan:
    needs: build-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: gitleaks/gitleaks-action@v2

  iac-scan:
    needs: build-test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: tfsec
        uses: aquasecurity/tfsec-action@v1.0.3
        with:
          working_directory: infrastructure

  # ---------- FASE 3: Bouwen, scannen en ondertekenen van image ----------
  build-sign-image:
    needs: [sast, dependency-scan, secrets-scan, iac-scan]
    runs-on: ubuntu-latest
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4
      - id: build
        run: |
          docker build -t registry.voorbeeld.nl/klantportaal:${{ github.sha }} .
          echo "digest=$(docker inspect --format='{{index .RepoDigests 0}}' registry.voorbeeld.nl/klantportaal:${{ github.sha }})" >> "$GITHUB_OUTPUT"

      - name: Scan image
        uses: aquasecurity/trivy-action@0.24.0
        with:
          image-ref: "registry.voorbeeld.nl/klantportaal:${{ github.sha }}"
          severity: "CRITICAL,HIGH"
          exit-code: "1"

      - name: Genereer SBOM
        uses: anchore/sbom-action@v0.17.0
        with:
          format: cyclonedx-json
          output-file: sbom.cyclonedx.json

      - run: docker push registry.voorbeeld.nl/klantportaal:${{ github.sha }}

      - name: Onderteken image met Cosign
        uses: sigstore/cosign-installer@v3
      - run: cosign sign --yes ${{ steps.build.outputs.digest }}

  # ---------- FASE 4: Deploy naar staging + DAST ----------
  deploy-staging:
    needs: build-sign-image
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/deploy.sh staging ${{ github.sha }}

  dast-scan:
    needs: deploy-staging
    runs-on: ubuntu-latest
    steps:
      - uses: zaproxy/action-baseline@v0.12.0
        with:
          target: "https://staging.klantportaal.voorbeeld.nl"
          fail_action: true

  # ---------- FASE 5: Policy-gate en productie-deployment ----------
  policy-gate:
    needs: dast-scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Valideer Kubernetes-manifests tegen OPA-beleid
        run: conftest test ./k8s --policy ./policies

  deploy-production:
    needs: policy-gate
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment:
      name: productie   # vereist handmatige goedkeuring in GitHub-omgevingsinstellingen
    steps:
      - uses: actions/checkout@v4
      - name: Verifieer handtekening vóór deployment
        run: |
          cosign verify 
            --certificate-identity-regexp "https://github.com/voorbeeld-bv/.*" 
            --certificate-oidc-issuer "https://token.actions.githubusercontent.com" 
            registry.voorbeeld.nl/klantportaal@${{ needs.build-sign-image.outputs.digest }}
      - run: ./scripts/deploy.sh production ${{ github.sha }}

16.3 Wat deze pijplijn illustreert

  • Parallellisatie: de vier scanjobs in fase 2 draaien gelijktijdig, zodat de doorlooptijd beperkt blijft.
  • Opeenvolgende afhankelijkheden: elke fase bouwt voort op een succesvolle vorige fase — een falende scan voorkomt dat een kwetsbaar artefact ooit wordt gebouwd, ondertekend of uitgerold.
  • Defense in depth: geen enkele controle staat op zichzelf; SAST, SCA, secretsdetectie, IaC-scanning, image-scanning, DAST en policy-validatie vangen elk een ander deel van het risicospectrum.
  • Herleidbaarheid: het SBOM en de digitale handtekening zorgen ervoor dat op elk moment kan worden vastgesteld waaruit een productie-artefact bestaat en dat het niet is gemanipuleerd.
  • Menselijke controle op het juiste moment: een geautomatiseerde pijplijn sluit een bewuste, menselijke goedkeuring vóór productie-deployment niet uit — die blijft zinvol als laatste, weloverwogen stap.

Hoofdstuk 17 — De toekomst van DevSecOps

17.1 Kunstmatige intelligentie in beveiliging

AI-ondersteunde tools worden steeds vaker ingezet om code te reviewen, kwetsbaarheden te prioriteren op basis van daadwerkelijke exploiteerbaarheid, en zelfs geautomatiseerd fixes voor te stellen. Tegelijkertijd gebruiken aanvallers AI om phishing, social engineering en het vinden van kwetsbaarheden te versnellen. Dit betekent dat DevSecOps-praktijken moeten meebewegen: AI-gegenereerde code vereist dezelfde — zo niet strengere — controles als door mensen geschreven code, aangezien deze tools ook onveilige patronen kunnen reproduceren.

17.2 Supply chain security als blijvend zwaartepunt

Naarmate softwareketens complexer worden, zal de aandacht voor SBOM's, ondertekende artefacten en herleidbare builds (zoals in het SLSA-raamwerk) verder toenemen. Regelgeving in verschillende regio's begint dit ook actief te stimuleren of te verplichten, wat supply chain-transparantie van een "best practice" naar een nalevingsvereiste verschuift.

17.3 Policy as code en platform engineering

De opkomst van platform engineering — het bouwen van interne developer platforms die gestandaardiseerde, vooraf beveiligde bouwstenen aanbieden — maakt het mogelijk om beveiliging "by default" aan te bieden. In plaats van dat elk team zelf een veilige pijplijn moet samenstellen, biedt een centraal platformteam kant-en-klare, reeds geharde templates aan ("golden paths"), waardoor veilige keuzes de gemakkelijkste keuzes worden.

17.4 Van reactief naar voorspellend

Waar huidige tooling vooral reageert op bekende kwetsbaarheidspatronen, ontwikkelt het vakgebied zich richting meer voorspellende risicoanalyse: het combineren van code-eigenschappen, historische incidentdata en runtime-gedrag om risico's te prioriteren vóórdat ze daadwerkelijk worden misbruikt. Dit vermindert de afhankelijkheid van het handmatig doorspitten van lange lijsten met scanbevindingen.

Blijf leren

DevSecOps is een vakgebied dat voortdurend verandert. Regelmatige bijscholing, het volgen van OWASP-projecten en het testen van nieuwe tooling in een veilige sandbox-omgeving zijn essentieel om niet achterop te raken.

Hoofdstuk 18 — Conclusie

DevSecOps is geen eindbestemming maar een doorlopende reis. Het draait om het inbouwen van beveiliging in elke fase van de softwarelevenscyclus — niet als vertragende blokkade, maar als geïntegreerd onderdeel van hoe teams werken. De belangrijkste inzichten uit dit boek laten zich samenvatten in een aantal kernboodschappen.

  1. Cultuur gaat vóór tooling. Zonder gedeelde verantwoordelijkheid en psychologische veiligheid leveren zelfs de beste scanners weinig op.
  2. Automatiseer wat herhaalbaar is, maar behoud menselijk oordeelsvermogen voor complexe, contextafhankelijke beslissingen.
  3. Shift left én shield right: beveiliging begint bij ontwerp en threat modeling, en eindigt nooit — ook niet na een succesvolle deployment.
  4. Meet wat ertoe doet, en gebruik metrics om te leren en te verbeteren, niet om af te rekenen.
  5. Begin klein, toon waarde, en breid vervolgens gestaag uit — grootschalige, geforceerde uitrol van tooling en beleid roept weerstand op en ondermijnt zichzelf.
  6. De software supply chain is onderdeel van het aanvalsoppervlak: beveilig niet alleen de applicatie, maar ook de keten die haar bouwt en uitlevert.

De concrete YAML-voorbeelden, diagrammen en checklists in dit boek zijn bedoeld als startpunt, niet als eindpunt. Elke organisatie heeft een eigen risicoprofiel, technologiestack en cultuur, en een goede DevSecOps-praktijk wordt altijd op maat doorontwikkeld. De reis begint met een eerste, kleine stap: één geautomatiseerde scan, één threat model, één gesprek tussen een ontwikkelaar en een security-specialist. Van daaruit groeit, stap voor stap, een organisatie die snelheid en veiligheid niet als tegenstelling ziet, maar als twee kanten van dezelfde medaille.

Bijlage A — Glossarium

TermBetekenis
CI/CDContinuous Integration / Continuous Delivery: geautomatiseerd bouwen, testen en uitleveren van software.
SASTStatic Application Security Testing: analyse van broncode zonder uitvoering.
DASTDynamic Application Security Testing: testen van een draaiende applicatie van buitenaf.
SCASoftware Composition Analysis: scannen van open source afhankelijkheden op kwetsbaarheden.
IaCInfrastructure as Code: infrastructuur gedefinieerd en beheerd als code.
SBOMSoftware Bill of Materials: gestructureerde lijst van alle componenten in een softwareproduct.
Policy as codeOrganisatiebeleid vastgelegd als machineleesbare, automatisch afdwingbare regels.
Shift leftHet naar voren halen van beveiligingsactiviteiten in de ontwikkelcyclus.
Shield rightHet continu bewaken en beschermen van systemen na deployment.
Threat modelingGestructureerd analyseren van mogelijke bedreigingen vóór en tijdens het ontwerp van een systeem.
STRIDERaamwerk voor het categoriseren van bedreigingen: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege.
Security gateGeautomatiseerd controlepunt in een pijplijn dat een build kan blokkeren bij een bevinding.
MTTRMean Time To Remediate: gemiddelde tijd tussen ontdekking en oplossing van een kwetsbaarheid.
SLSASupply-chain Levels for Software Artifacts: raamwerk voor build-integriteit en herleidbaarheid.
Secrets managementHet veilig opslaan, distribueren en roteren van gevoelige waarden zoals wachtwoorden en API-sleutels.
OPAOpen Policy Agent: cloud-native policy-engine, met de taal Rego.
SIEMSecurity Information and Event Management: platform voor het centraal verzamelen en analyseren van beveiligingslogs.
Container escapeEen aanval waarbij een proces vanuit een container toegang krijgt tot de onderliggende hostmachine.
Least privilegeHet principe dat elk proces, elke gebruiker of elke service enkel de minimaal noodzakelijke rechten krijgt.
Zero trustBeveiligingsmodel waarbij geen enkel verzoek standaard wordt vertrouwd, ongeacht de herkomst binnen of buiten het netwerk.

Bijlage B — DevSecOps-checklist

B.1 Ontwerp en planning

  • Is er een threat model opgesteld voor nieuwe of significant gewijzigde architectuur?
  • Zijn vertrouwensgrenzen (trust boundaries) expliciet in kaart gebracht?
  • Is het principe van minimale rechten toegepast in het ontwerp?

B.2 Ontwikkeling

  • Is er een pre-commit hook actief voor secretsdetectie?
  • Wordt alle externe invoer server-side gevalideerd?
  • Bevat de pull request-template een beveiligingschecklist voor reviewers?

B.3 Build en CI

  • Draait SAST bij elke pull request?
  • Draait SCA/dependency-scanning bij elke build?
  • Wordt een SBOM gegenereerd en bewaard bij elke release?
  • Worden container-images gescand vóórdat ze naar de registry worden gepusht?
  • Wordt infrastructuurcode (Terraform, Kubernetes-manifests) gescand op misconfiguraties?

B.4 Release en deployment

  • Worden artefacten digitaal ondertekend en geverifieerd vóór deployment?
  • Draait een DAST-scan tegen de staging-omgeving?
  • Wordt policy as code afgedwongen vóór productie-deployment?
  • Is er een handmatige goedkeuringsstap voor productie-releases met verhoogd risico?

B.5 Operatie en monitoring

  • Is runtime-monitoring actief op productiesystemen?
  • Zijn beveiligingsrelevante gebeurtenissen gestructureerd gelogd en centraal doorzoekbaar?
  • Is er een actueel, geoefend incident response-draaiboek?
  • Worden security-metrics periodiek gerapporteerd en besproken?

B.6 Organisatie

  • Zijn er security champions actief binnen ontwikkelteams?
  • Is er een blameless cultuur rondom het melden van fouten en incidenten?
  • Krijgen teams structurele training in secure coding en threat modeling?

Bijlage C — Aanbevolen bronnen en tooling

C.1 Raamwerken en standaarden

  • OWASP Top 10 — meest voorkomende kwetsbaarheidscategorieën in webapplicaties.
  • OWASP SAMM (Software Assurance Maturity Model) — volwassenheidsmodel voor secure development.
  • NIST Cybersecurity Framework en NIST SP 800-61 (incident response).
  • SLSA (Supply-chain Levels for Software Artifacts).
  • CIS Benchmarks — hardeningsrichtlijnen voor besturingssystemen, containers en cloud-platformen.

C.2 Veelgebruikte open source tooling per categorie

CategorieVoorbeelden
SASTSemgrep, CodeQL, SonarQube
SCA / dependency-scanningTrivy, Grype, OWASP Dependency-Check
SecretsdetectieGitleaks, TruffleHog
IaC-scanningtfsec, Checkov, Terrascan
Container image-scanningTrivy, Grype, Clair
DASTOWASP ZAP, Nuclei
Policy as codeOpen Policy Agent (OPA), Conftest, Kyverno
Runtime-beveiligingFalco, Tetragon
Supply chain / ondertekeningSigstore/Cosign, Syft (SBOM), in-toto
Threat modelingOWASP Threat Dragon, pytm

Dit e-book biedt een startpunt voor de implementatie van DevSecOps binnen een organisatie. Voor verdieping op specifieke onderwerpen wordt aangeraden de documentatie van bovenstaande tools en raamwerken te raadplegen, aangezien deze voortdurend worden bijgewerkt met nieuwe functionaliteit en richtlijnen.