Aller au contenu principal

Exercices et Projets


1 - Exercices pratiques

Exercice 1 : Pipeline SAST

Objectif : Configurer un pipeline avec SAST scanning.

Solution
# .github/workflows/sast.yml
name: SAST Pipeline

on: [push, pull_request]

jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: GitLeaks Secrets Scan
uses: gitleaks/gitleaks-action@v2

- name: Semgrep SAST
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/owasp-top-ten

- name: SonarQube Scan
uses: sonarsource/sonarqube-scan-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

Exercice 2 : Container Security

Objectif : Scanner et sécuriser une image Docker.

Solution
# Dockerfile sécurisé
FROM node:20-alpine@sha256:abc123...

RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup

WORKDIR /app
COPY --chown=appuser:appgroup package*.json ./
RUN npm ci --only=production

COPY --chown=appuser:appgroup src/ ./src/

USER appuser
EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider http://localhost:8080/health || exit 1

CMD ["node", "src/index.js"]
# Pipeline scan
- name: Build Image
run: docker build -t myapp:${{ github.sha }} .

- name: Trivy Scan
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'

- name: Hadolint
uses: hadolint/hadolint-[email protected]
with:
dockerfile: Dockerfile

Exercice 3 : Kyverno Policies

Objectif : Créer des policies Kubernetes avec Kyverno.

Solution
# require-security-context.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-security-context
spec:
validationFailureAction: enforce
rules:
- name: require-run-as-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Pods must run as non-root"
pattern:
spec:
securityContext:
runAsNonRoot: true
containers:
- securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: enforce
rules:
- name: require-limits
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Containers must have resource limits"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"

Exercice 4 : Secrets avec Vault

Objectif : Intégrer HashiCorp Vault dans Kubernetes.

Solution
# Installation Vault
helm install vault hashicorp/vault \
--set "server.dev.enabled=true"

# Configuration
kubectl exec -it vault-0 -- vault secrets enable -path=secret kv-v2
kubectl exec -it vault-0 -- vault kv put secret/myapp/config \
api_key="sk-12345" \
db_password="secure-pass"

# Auth Kubernetes
kubectl exec -it vault-0 -- vault auth enable kubernetes
kubectl exec -it vault-0 -- vault write auth/kubernetes/config \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"

# Role
kubectl exec -it vault-0 -- vault write auth/kubernetes/role/myapp \
bound_service_account_names=myapp-sa \
bound_service_account_namespaces=default \
policies=myapp-policy \
ttl=1h
# Pod avec Vault injection
apiVersion: v1
kind: Pod
metadata:
name: myapp
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
vault.hashicorp.com/agent-inject-secret-config: "secret/data/myapp/config"
spec:
serviceAccountName: myapp-sa
containers:
- name: app
image: myapp:latest

2 - Projet complet : Secure Application Deployment

Architecture

Pipeline complet

# .github/workflows/secure-deploy.yml
name: Secure Deployment Pipeline

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

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
# Stage 1: Pre-commit checks
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Secrets Detection
uses: gitleaks/gitleaks-action@v2

- name: Commit Lint
uses: pre-commit/[email protected]

# Stage 2: SAST
sast:
runs-on: ubuntu-latest
needs: pre-commit
steps:
- uses: actions/checkout@v4

- name: Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: p/security-audit p/owasp-top-ten

- name: CodeQL Analysis
uses: github/codeql-action/analyze@v2

# Stage 3: SCA
sca:
runs-on: ubuntu-latest
needs: pre-commit
steps:
- uses: actions/checkout@v4

- name: Snyk SCA
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high

# Stage 4: Build & Container Scan
build:
runs-on: ubuntu-latest
needs: [sast, sca]
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Hadolint
uses: hadolint/hadolint-[email protected]

- name: Build Image
run: docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .

- name: Trivy Scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
format: 'sarif'
exit-code: '1'
severity: 'CRITICAL,HIGH'

- name: Generate SBOM
run: syft ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} -o cyclonedx-json > sbom.json

- name: Sign Image
run: cosign sign --key env://COSIGN_KEY ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
env:
COSIGN_KEY: ${{ secrets.COSIGN_KEY }}

- name: Push Image
run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

# Stage 5: IaC Scan
iac-scan:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4

- name: Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: kubernetes/
framework: kubernetes

# Stage 6: Deploy
deploy:
runs-on: ubuntu-latest
needs: iac-scan
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/checkout@v4

- name: Deploy to Kubernetes
run: |
kubectl apply -f kubernetes/
env:
KUBECONFIG: ${{ secrets.KUBECONFIG }}

Kyverno Policies

# policies/security-policies.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: secure-deployment
spec:
validationFailureAction: enforce
rules:
# Require signed images
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/*"
attestors:
- entries:
- keyless:
subject: "*@github.com"
issuer: "https://token.actions.githubusercontent.com"

# Require security context
- name: require-security-context
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Security context required"
pattern:
spec:
securityContext:
runAsNonRoot: true
containers:
- securityContext:
allowPrivilegeEscalation: false

3 - Quiz de révision

  1. Qu'est-ce que "Shift Left" en sécurité ?

  2. Quelle est la différence entre SAST et DAST ?

  3. Qu'est-ce qu'un SBOM ?

  4. Comment sécuriser les secrets dans Kubernetes ?

  5. Qu'est-ce que Kyverno ?

Réponses
  1. Shift Left : Intégrer la sécurité plus tôt dans le cycle de développement pour détecter les problèmes avant la production.

  2. SAST : Analyse statique du code source (avant exécution). DAST : Analyse dynamique de l'application en cours d'exécution.

  3. SBOM (Software Bill of Materials) : Liste complète des composants, versions et dépendances d'une application.

  4. Utiliser un Secrets Manager externe (Vault, AWS Secrets Manager) avec External Secrets Operator ou Vault Agent Injector.

  5. Kyverno : Policy engine Kubernetes-native pour valider, muter et générer des ressources.


4 - Certifications

Certifications recommandées

CertificationFournisseurFocus
Certified Kubernetes Security (CKS)CNCFK8s Security
AWS Security SpecialtyAWSAWS Security
GIAC Cloud Security (GCLD)SANSCloud Security
Certified DevSecOps Professional (CDP)Practical DevSecOpsDevSecOps
CompTIA Security+CompTIAFundamentals

Ressources


Résumé du cours

Félicitations ! Vous avez complété le cours DevSecOps.

Vous maîtrisez maintenant :

  • Les principes Shift Left
  • Les outils SAST et DAST
  • La sécurité des conteneurs
  • La Supply Chain Security
  • La gestion des secrets
  • Compliance as Code
  • L'Incident Response

Prochaines étapes

  • Pratiquer avec des labs
  • Passer la certification CKS
  • Implémenter DevSecOps dans votre organisation
  • Contribuer à des projets open source de sécurité

← Retour à la table des matières