MFormations
Modern DevOps Engineering

Chapitre 12

12 - Securite DevOps

12 - Securite DevOps

Chapitre 12 : Securite DevOps

12.1 DevSecOps Pipeline

12.1.1 Shift Left Security

Le "Shift Left" consiste a integrer la securite le plus tot possible dans le cycle de developpement :

Plan → Code → Build → Test → Deploy → Operate
  │      │       │       │       │        │
  │      │       │       │       │        │
Secure  SAST   SCA     DAST   Image    Runtime
Design          Audit          Signing  Security

12.1.2 SAST (Static Application Security Testing)

SAST analyse le code source sans l'executer :

# GitHub Actions - SAST with Semgrep
name: SAST
on: [pull_request]

jobs:
  semgrep:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: semgrep/semgrep-action@v1
        with:
          config: p/python p/owasp-top-ten p/secrets
          publishToken: ${{ secrets.SEMGREP_TOKEN }}

Outils SAST populaires :

  • Semgrep : Regles personnalisables, large couverture
  • SonarQube : Analyse de qualite et securite
  • CodeQL (GitHub) : Analyse semantique avancee
  • Checkmarx : Solution enterprise
  • Fortify : Analyse de vulnerabilites

12.1.3 DAST (Dynamic Application Security Testing)

DAST teste l'application en cours d'execution :

# GitLab CI - DAST with OWASP ZAP
stages:
  - dast

dast:
  stage: dast
  image: owasp/zap2docker-stable
  script:
    - zap-full-scan.py -t https://staging.example.com -r report.html
  artifacts:
    paths:
      - report.html

12.1.4 Dependency Scanning

Analyse des vulnerabilites dans les dependances :

# GitHub Actions - Dependency Review
name: Dependency Review
on: [pull_request]

jobs:
  dependency-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/dependency-review-action@v3
        with:
          fail-on-severity: high
          deny-licenses: LGPL-2.0

Exemple de vulnerabilite detectee :

Package: lodash@4.17.20
Severity: CRITICAL (CVE-2021-23337)
CVSS: 9.1
Recommendation: Upgrade to 4.17.21+

12.2 HashiCorp Vault

12.2.1 Architecture Vault

Vault est un gestionnaire de secrets enterprise :

Application ──> Vault API ──> Auth Method (Kubernetes, LDAP, JWT)
                                   │
                              Secret Engine
                                   │
                              Storage Backend
                             (Consul, Raft, S3)

Composants cles :

  • Auth Methods : Kubernetes, LDAP, JWT, AppRole
  • Secret Engines : KV, Database, AWS, PKI, Transit
  • Audit Device : Journalisation de tous les acces
  • Storage Backend : Raft (integre), Consul, S3

12.2.2 Deploiement Vault sur Kubernetes

# vault-helm-values.yaml
server:
  ha:
    enabled: true
    replicas: 3
    raft:
      enabled: true
      config: |
        ui = true
        listener "tcp" {
          address = "0.0.0.0:8200"
          cluster_address = "0.0.0.0:8201"
          tls_disable = true
        }
        storage "raft" {
          path = "/vault/data"
        }
        service_registration "kubernetes" {}

  service:
    enabled: true

  ingress:
    enabled: true
    hosts:
      - vault.example.com

ui:
  enabled: true

12.2.3 Dynamic Secrets

Les secrets dynamiques sont generes a la demande :

# Activer le secret engine Database
vault secrets enable database

# Configurer la connexion PostgreSQL
vault write database/config/postgres-db \
    plugin_name=postgresql-database-plugin \
    allowed_roles="app-role" \
    connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mydb" \
    username="vault-admin" \
    password="secret"

# Creer un role
vault write database/roles/app-role \
    db_name=postgres-db \
    creation_statements="CREATE USER \"{{name}}\" WITH PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
    default_ttl="1h" \
    max_ttl="24h"

# Generer un credential
vault read database/creds/app-role
# Key                Value
# ---                -----
# lease_id           database/creds/app-role/abc123
# lease_duration     1h
# password           aB3xY7z...
# username           v-token-app-role-xyz789

12.2.4 Vault Agent Injector

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-with-secrets
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "app"
    vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/app-role"
    vault.hashicorp.com/agent-inject-template-db-creds: |
      {{- with secret "database/creds/app-role" -}}
      export DB_USERNAME="{{ .Data.username }}"
      export DB_PASSWORD="{{ .Data.password }}"
      {{- end -}}
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
    spec:
      serviceAccountName: app
      containers:
        - name: app
          image: myapp:latest
          env:
            - name: DB_USERNAME
              valueFrom:
                secretKeyRef:
                  name: dynamic-db-creds
                  key: username

12.2.5 Transit Engine (Chiffrement)

# Activer le transit engine
vault secrets enable transit

# Creer une cle de chiffrement
vault write -f transit/keys/app-key

# Chiffrer des donnees
vault write transit/encrypt/app-key plaintext=$(base64 <<< "sensitive-data")

# Dechiffrer
vault write transit/decrypt/app-key ciphertext="vault:v1:abc123..."

12.3 OPA/Gatekeeper et Kyverno

12.3.1 OPA (Open Policy Agent)

OPA est un moteur de politique generaliste :

# deny-no-roles.rego
package kubernetes.admission

deny[msg] {
    input.request.operation == "CREATE"
    not input.request.object.spec.containers[_].securityContext.runAsNonRoot
    
    msg = sprintf("Container %v must run as non-root", [input.request.object.metadata.name])
}

deny[msg] {
    input.request.operation == "CREATE"
    input.request.object.spec.containers[_].resources.limits == {}
    
    msg = sprintf("Container %v must have resource limits", [input.request.object.metadata.name])
}

12.3.2 Gatekeeper

Gatekeeper est l'implementation Kubernetes d'OPA :

# constraint-template.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        violation[{"msg": msg}] {
          input.review.object.metadata.labels[required_label] == ""
          required_label := input.parameters.labels[_]
          msg := sprintf("Missing label: %v", [required_label])
        }
---
# constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
    namespaces:
      - "production"
  parameters:
    labels:
      - "team"
      - "cost-center"

12.3.3 Kyverno

Kyverno est un policy engine natif Kubernetes :

# kyverno-policy.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: check-team-label
      match:
        any:
          - resources:
              kinds:
                - Pod
                - Deployment
              namespaces:
                - production
      validate:
        message: "Label 'team' is required in production"
        pattern:
          metadata:
            labels:
              team: "?*"
    - name: block-privileged
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Privileged containers are not allowed"
        pattern:
          spec:
            containers:
              - securityContext:
                  privileged: false
    - name: require-resource-limits
      match:
        any:
          - resources:
              kinds:
                - Deployment
      validate:
        message: "Resource limits are required"
        pattern:
          spec:
            template:
              spec:
                containers:
                  - resources:
                      limits:
                        memory: "?*"
                        cpu: "?*"

12.4 Securite de la Supply Chain

12.4.1 SBOM (Software Bill of Materials)

Un SBOM est une liste de tous les composants d'un logiciel :

# Generer un SBOM CycloneDX avec Syft
syft packages myapp:latest -o cyclonedx-json > sbom.json

# Analyser le SBOM
grype sbom:sbom.json --fail-on=high

# Exemple de SBOM
cat sbom.json | jq '.components[] | {name, version, type}'
{
  "name": "flask",
  "version": "2.3.2",
  "type": "library"
}
{
  "name": "python",
  "version": "3.11.0",
  "type": "application"
}

12.4.2 Image Signing avec Cosign

Cosign permet de signer et verifier des images conteneurs :

# Generer une paire de cles
cosign generate-key-pair

# Signer une image
cosign sign --key cosign.key myregistry.io/myapp:latest

# Verifier une signature
cosign verify --key cosign.pub myregistry.io/myapp:latest

# Verification dans un pipeline
cosign verify-attestation --key cosign.pub myregistry.io/myapp:latest | jq .

12.4.3 SLSA Framework

SLSA (Supply chain Levels for Software Artifacts) definit des niveaux de securite :

Level 1: Build process documented
Level 2: Signed provenance
Level 3: Hardened build platform
Level 4: Hermetic, reproducible builds

Implementation SLSA 3 avec GitHub Actions :

# .github/workflows/slsa.yml
name: SLSA
on:
  workflow_dispatch:
  push:
    branches: [main]

jobs:
  build:
    permissions:
      id-token: write
      contents: read
      actions: read
    uses: slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml@v1.9.0
    with:
      go-version: 1.21
      evaluated-envs: "GOFLAGS=-v"

12.4.4 Notary

Notary est un systeme de confiance pour les images conteneurs :

# Initialiser un repository
notary init myregistry.io/myapp

# Signer une nouvelle version
notary add myregistry.io/myapp v1.2.3 --publish

# Verifier
notary verify myregistry.io/myapp@v1.2.3

12.5 Conformite

12.5.1 CIS Benchmarks

Les CIS (Center for Internet Security) Benchmarks sont des guides de securite :

# Executer CIS Benchmark avec kube-bench
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml

# Resultats
kubectl logs job/kube-bench
# [PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive
# [FAIL] 1.2.2 Ensure that the --basic-auth-file argument is not set
# [WARN] 1.2.5 Ensure that the --kubelet-https argument is set to true

12.5.2 SOC 2 Compliance

SOC 2 est un standard d'audit pour les fournisseurs de services :

Les 5 principes Trust Service Criteria :

  1. Security : Protection contre les acces non autorises
  2. Availability : Disponibilite du systeme
  3. Processing Integrity : Traitement autorise et complete
  4. Confidentiality : Protection des informations confidentielles
  5. Privacy : Collecte et traitement des donnees personnelles

Exemple de controles SOC 2 DevOps :

# Code Review Policy
code_review:
  required_approvers: 2
  required_checks:
    - semgrep-sast
    - dependency-review
    - snyk-scan

# Access Control
access_control:
  ci_cd:
    - github_actions: ["ci", "cd"]
    - vault: ["read-db-creds", "read-kv"]
    - kubernetes: ["view", "exec"]

# Audit Logging
audit:
  - github_audit_log: true
  - vault_audit_log: true
  - kubernetes_audit_log: true
  - retention_days: 365

12.6 Resume

  • Le DevSecOps integre la securite a chaque etape du pipeline
  • SAST analyse le code, DAST teste l'application en cours d'execution
  • Vault centralise la gestion des secrets avec des secrets dynamiques
  • OPA/Gatekeeper et Kyverno permettent le Policy as Code sur Kubernetes
  • Les SBOM (CycloneDX) listent tous les composants logiciels
  • Cosign signe les images conteneurs pour garantir leur integrite
  • SLSA definit les niveaux de securite de la supply chain
  • CIS Benchmarks et SOC 2 sont les standards de conformite