Supply Chain Security
1 - Risques Supply Chain
1.1 Attaques récentes
| Attaque | Année | Impact |
|---|---|---|
| SolarWinds | 2020 | 18,000+ organisations |
| Codecov | 2021 | Secrets exposés |
| Log4Shell | 2021 | Millions de systèmes |
| ua-parser-js | 2021 | Malware npm |
1.2 Vecteurs d'attaque
2 - Software Composition Analysis (SCA)
2.1 Outils SCA
| Outil | Type | Features |
|---|---|---|
| Snyk | Commercial | SCA + Fix PRs |
| Dependabot | GitHub natif | Auto PRs |
| OWASP Dependency-Check | OSS | CVE scanning |
| Renovate | OSS | Dependency updates |
| WhiteSource | Commercial | Enterprise |
2.2 Snyk
# GitHub Action
- name: Snyk SCA
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: test
args: --severity-threshold=high --all-projects
# CLI
snyk test
# Monitor (push to dashboard)
snyk monitor
# Fix vulnerabilities
snyk wizard
2.3 Dependabot
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
groups:
production-dependencies:
patterns:
- "*"
exclude-patterns:
- "@types/*"
- "eslint*"
ignore:
- dependency-name: "aws-sdk"
versions: ["3.x"]
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
2.4 OWASP Dependency-Check
- name: OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'my-app'
path: '.'
format: 'HTML'
args: >-
--failOnCVSS 7
--enableRetired
3 - SBOM (Software Bill of Materials)
3.1 Concept
3.2 Formats SBOM
| Format | Standard | Usage |
|---|---|---|
| SPDX | ISO/IEC | Large adoption |
| CycloneDX | OWASP | Security-focused |
| SWID | ISO/IEC | Software ID |
3.3 Générer un SBOM
# Syft (CycloneDX)
syft myapp:latest -o cyclonedx-json > sbom.json
# Trivy (SPDX)
trivy image --format spdx-json --output sbom-spdx.json myapp:latest
# npm (CycloneDX)
npx @cyclonedx/cyclonedx-npm --output-file sbom.xml
3.4 Pipeline avec SBOM
- name: Generate SBOM
run: |
syft $IMAGE -o cyclonedx-json > sbom.json
- name: Scan SBOM for vulnerabilities
run: |
grype sbom:sbom.json --fail-on high
- name: Attest SBOM
run: |
cosign attest --predicate sbom.json \
--type cyclonedx \
--key $COSIGN_KEY \
$IMAGE
4 - Signature et attestation
4.1 Sigstore / Cosign
# Générer une clé
cosign generate-key-pair
# Signer une image
cosign sign --key cosign.key myregistry.io/myapp:v1.0.0
# Vérifier
cosign verify --key cosign.pub myregistry.io/myapp:v1.0.0
# Keyless signing (OIDC)
cosign sign myregistry.io/myapp:v1.0.0
# Vérifier keyless
cosign verify --certificate-identity [email protected] \
--certificate-oidc-issuer https://accounts.google.com \
myregistry.io/myapp:v1.0.0
4.2 SLSA (Supply-chain Levels for Software Artifacts)
| Level | Requirements |
|---|---|
| SLSA 1 | Documentation du build |
| SLSA 2 | Hosted build, authenticated provenance |
| SLSA 3 | Source et build hardened |
| SLSA 4 | Two-party review, hermetic builds |
4.3 SLSA Provenance
# GitHub Action pour SLSA provenance
- name: Generate SLSA Provenance
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
with:
image: ${{ env.IMAGE }}
digest: ${{ env.DIGEST }}
// Exemple de provenance SLSA
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [{
"name": "myapp",
"digest": { "sha256": "abc123..." }
}],
"predicate": {
"builder": { "id": "https://github.com/actions/runner" },
"buildType": "https://github.com/slsa-framework/slsa-github-generator",
"invocation": {
"configSource": {
"uri": "git+https://github.com/myorg/myapp@refs/heads/main",
"digest": { "sha1": "def456..." }
}
},
"materials": [
{
"uri": "git+https://github.com/myorg/myapp",
"digest": { "sha1": "def456..." }
}
]
}
}
5 - Secure Build Pipeline
5.1 GitHub Actions Hardening
name: Secure Build
on:
push:
branches: [main]
# Permissions minimales
permissions:
contents: read
packages: write
id-token: write # Pour OIDC
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
# Pin des actions par SHA
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
with:
node-version: '20'
# Vérifier les checksums
- name: Verify dependencies
run: npm ci --ignore-scripts
# Build hermétique
- name: Build
run: npm run build
env:
NODE_ENV: production
5.2 Dependency Pinning
// package-lock.json - lockfile obligatoire
{
"lockfileVersion": 3,
"packages": {
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-...=="
}
}
}
# Dockerfile - Image pinning par digest
FROM node:20-alpine@sha256:abc123def456...
5.3 Reproducible Builds
# Build reproductible
FROM node:20-alpine AS builder
WORKDIR /app
# Copier uniquement package files d'abord
COPY package*.json ./
RUN npm ci --ignore-scripts
# Puis le code
COPY . .
RUN npm run build
# Timestamps constants pour reproductibilité
RUN find /app/dist -type f -exec touch -t 202401010000 {} \;
6 - Admission Controllers
6.1 Kyverno Policies
# Exiger des images signées
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: enforce
rules:
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
subject: "https://github.com/myorg/*"
issuer: "https://token.actions.githubusercontent.com"
6.2 OPA Gatekeeper
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sallowedrepos
spec:
crd:
spec:
names:
kind: K8sAllowedRepos
validation:
openAPIV3Schema:
type: object
properties:
repos:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedrepos
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not strings.any_prefix_match(container.image, input.parameters.repos)
msg := sprintf("image '%v' not from allowed repos", [container.image])
}
Résumé
Dans ce chapitre, nous avons appris :
- Les risques supply chain
- Le SCA (Snyk, Dependabot, OWASP)
- Les SBOM et leur génération
- La signature avec Cosign/Sigstore
- Les niveaux SLSA
- Les Admission Controllers
Prochaine étape
Dans le prochain chapitre, nous verrons la Gestion des secrets.
→ Chapitre suivant : Gestion des secrets