Confidentialite¶
Les miroirs de paquets sont classes Interne dans le modèle de classification. Bien que les paquets caches soient d'origine publique, la configuration du miroir, les patterns d'utilisation et les paquets internes hosted constituent des informations sensibles.
Risques spécifiques aux miroirs¶
Les miroirs révèlent la stack technique¶
Un attaquant ayant accès au miroir interne peut extraire :
| Information exposee | Exemple | Risque |
|---|---|---|
| Technologies utilisees | tensorflow, pytorch, react | Cartographie de la stack |
| Versions des dependances | lodash@4.17.20 | Identification de vulnabilites connues |
| Paquets internes (hosted) | @company/auth-sdk | Reverse engineering des services |
| Fréquence de build | 200 pulls Docker/jour | Évaluation de l'activité |
| Équipes et projets | team-data/ml-pipeline | Organigramme technique |
Les miroirs peuvent propager des paquets malveillants¶
Un dépôt proxy cache automatiquement tout paquet demande par un client. Si un développeur installe un paquet malveillant (typosquatting, dependency confusion), le miroir le cache et le rend disponible pour tous les autres utilisateurs.
graph TD
Attaquant["Attaquant"] -->|Publie paquet malveillant| npm["npm public"]
DevA["Developpeur A"] -->|npm install malicious-pkg| Nexus["Nexus proxy"]
Nexus -->|Cache le paquet| Cache["Cache local"]
DevB["Developpeur B"] -->|npm install malicious-pkg| Cache
DevC["Developpeur C"] -->|npm install malicious-pkg| Cache
Cache -->|Servi depuis le cache| DevB
Cache -->|Servi depuis le cache| DevC Conséquence : un miroir sans scanning amplifie la propagation des paquets malveillants.
Scanning de vulnerabilites¶
Integration Trivy¶
Trivy peut scanner les artefacts caches dans Nexus, soit de manière proactive (scan planifie) soit dans le pipeline CI/CD.
Scan planifie des images Docker¶
#!/bin/bash
# /opt/scripts/scan-nexus-images.sh
# Execute par cron toutes les nuits
NEXUS_URL="https://nexus.internal.company.io"
NEXUS_USER="scanner"
NEXUS_PASS="PASSWORD"
REPORT_DIR="/var/reports/trivy"
# Lister les images Docker du depot hosted
IMAGES=$(curl -s -u "${NEXUS_USER}:${NEXUS_PASS}" \
"${NEXUS_URL}/service/rest/v1/search?repository=docker-hosted" \
| jq -r '.items[] | "\(.name):\(.version)"')
mkdir -p "${REPORT_DIR}/$(date +%Y-%m-%d)"
for IMAGE in ${IMAGES}; do
echo "Scanning ${IMAGE}..."
trivy image \
--server https://trivy-server.internal:4954 \
--severity HIGH,CRITICAL \
--format json \
--output "${REPORT_DIR}/$(date +%Y-%m-%d)/${IMAGE//\//_}.json" \
"docker.internal.company.io/${IMAGE}"
done
Scan dans le pipeline CI/CD¶
# Etape de scan avant le push vers le depot hosted
- name: Scan for vulnerabilities
run: |
trivy image \
--severity HIGH,CRITICAL \
--exit-code 1 \
--ignore-unfixed \
docker.internal.company.io/myapp:${{ github.sha }}
Integration Grype¶
# Scanner une image Docker
grype docker.internal.company.io/myapp:v1.0.0 \
--fail-on critical \
--output json > grype-report.json
# Scanner un lockfile npm
grype sbom:npm-lockfile.json
# Scanner un requirements.txt Python
grype sbom:requirements.txt
Tableau de bord des vulnerabilites¶
| Metrique | Source | Alerte si |
|---|---|---|
| Images avec vulnerabilites HIGH | Trivy scan planifie | > 0 dans les images de production |
| Images avec vulnerabilites CRIT | Trivy scan planifie | > 0 (toute image) |
| Paquets npm avec CVE connues | npm audit via Nexus | Sévérité >= high |
| Paquets Python avec CVE | pip-audit | Sévérité >= high |
| Delai moyen de correction | Dashboard interne | > 7 jours pour CRITICAL |
RBAC (Rôle-Based Access Control)¶
Modèle de rôles¶
Nexus offre un système de rôles et privileges granulaire. Le modèle recommande separe les droits de lecture et d'écriture par type de dépôt.
| Rôle | Privileges | Affecte a |
|---|---|---|
nx-reader | Lecture sur tous les dépôts group | Tous les développeurs |
npm-deployer | Écriture sur npm-hosted | Pipeline CI/CD npm |
pypi-deployer | Écriture sur pypi-hosted | Pipeline CI/CD Python |
maven-deployer | Écriture sur maven-hosted-* | Pipeline CI/CD Java |
docker-deployer | Écriture sur docker-hosted | Pipeline CI/CD Docker |
nx-admin | Administration complète | Équipe SRE/infra (2-3 personnes) |
Configuration RBAC via API¶
# Creer un role de lecteur
curl -u admin:PASSWORD -X POST \
'https://nexus.internal.company.io/service/rest/v1/security/roles' \
-H 'Content-Type: application/json' \
-d '{
"id": "nx-reader",
"name": "Nexus Reader",
"description": "Lecture seule sur tous les depots group",
"privileges": [
"nx-repository-view-*-*-browse",
"nx-repository-view-*-*-read",
"nx-search-read"
]
}'
# Creer un role de deploiement Docker
curl -u admin:PASSWORD -X POST \
'https://nexus.internal.company.io/service/rest/v1/security/roles' \
-H 'Content-Type: application/json' \
-d '{
"id": "docker-deployer",
"name": "Docker Deployer",
"description": "Push vers docker-hosted",
"privileges": [
"nx-repository-view-docker-docker-hosted-browse",
"nx-repository-view-docker-docker-hosted-read",
"nx-repository-view-docker-docker-hosted-add",
"nx-repository-view-docker-docker-hosted-edit"
]
}'
# Creer un utilisateur de service pour le CI/CD
curl -u admin:PASSWORD -X POST \
'https://nexus.internal.company.io/service/rest/v1/security/users' \
-H 'Content-Type: application/json' \
-d '{
"userId": "ci-docker",
"firstName": "CI",
"lastName": "Docker",
"emailAddress": "ci-docker@company.io",
"password": "GENERATED_PASSWORD",
"status": "active",
"roles": ["docker-deployer", "nx-reader"]
}'
Un compte de service par pipeline
Créer un compte de service dedie par pipeline ou par équipe, plutôt qu'un compte partage. Cela permet un audit précis et la revocation sans impact sur les autres équipes.
Audit des telechargements¶
Logs d'accès Nexus¶
Nexus enregistre chaque opération dans les request logs :
# /nexus-data/log/request.log
2026-04-16 10:30:15 ci-docker GET /repository/docker-group/v2/library/alpine/manifests/latest 200
2026-04-16 10:30:16 ci-docker GET /repository/docker-group/v2/library/alpine/blobs/sha256:abc123 200
2026-04-16 10:31:00 deployer PUT /repository/npm-hosted/@company/auth-sdk/-/auth-sdk-1.0.0.tgz 201
Centralisation des logs¶
# Filebeat configuration pour collecter les logs Nexus
filebeat.inputs:
- type: log
paths:
- /opt/nexus/data/log/request.log
fields:
service: nexus
type: access
multiline:
pattern: '^\d{4}-\d{2}-\d{2}'
negate: true
match: after
output.elasticsearch:
hosts: ["https://es.internal.company.io:9200"]
index: "nexus-access-%{+yyyy.MM.dd}"
Requêtes d'audit typiques¶
| Question d'audit | Requête |
|---|---|
Qui a publie l'image myapp:v1.2.3 ? | PUT /repository/docker-hosted/*/myapp/manifests/* |
| Quels paquets npm ont ete telecharges cette semaine ? | GET /repository/npm-group/ + agregation par paquet |
| Quels comptes utilisent le plus de bande passante ? | Agregation par userId + somme des tailles |
| Y a-t-il eu des telechargements depuis des IP inconnues ? | Filtre par IP source hors plages autorisees |
Segmentation réseau¶
Principe : seule la zone CI/CD accede au miroir¶
Les miroirs ne doivent pas etre accessibles depuis n'importe quel poste. La segmentation réseau recommandee :
graph TD
Dev["Zone Developpeurs<br/>(postes de travail, VPN)<br/><br/>Acces INTERDIT directement aux miroirs<br/>Utilisent le proxy via le pipeline CI/CD"]
Dev -->|Push code → Git| CICD
CICD["Zone CI/CD<br/>(runners Gitea Actions, agents Jenkins)<br/><br/>Acces AUTORISE aux miroirs (pull + push)<br/>Seule zone qui interagit avec Nexus"]
CICD --> Chain["Zone Chaine logicielle<br/>(Nexus, Gitea, SonarQube, Harbor)<br/><br/>Nexus accede a Internet (HTTPS sortant)<br/>pour telecharger depuis les registres publics"] Regles de firewall¶
| Source | Destination | Port | Action | Commentaire |
|---|---|---|---|---|
| Zone CI/CD | Nexus (reverse proxy) | 443 | ALLOW | Pull/push via HTTPS |
| Zone Développeurs | Nexus (reverse proxy) | 443 | DENY | Pas d'accès direct (par defaut) |
| Zone Développeurs | Nexus (reverse proxy) | 443 | ALLOW | Optionnel : lecture seule, si requis |
| Nexus | Internet | 443 | ALLOW | Telechargement upstream |
| Nexus | PostgreSQL | 5432 | ALLOW | Base de metadonnees |
| Monitoring | Nexus | 8081 | ALLOW | Metriques Prometheus |
| Tout autre | Nexus | * | DENY | Refus par defaut |
Accès développeurs : évaluer le besoin
Certaines équipes ont besoin d'un accès direct au miroir (par exemple pour docker pull depuis un poste de développement). Dans ce cas, autoriser uniquement la lecture (dépôts group) et interdire l'écriture. L'idéal reste de tout faire passer par le pipeline CI/CD.
Chiffrement du stockage¶
Chiffrement au repos¶
| Backend stockage | Méthode de chiffrement | Configuration |
|---|---|---|
| Fichier local | LUKS (chiffrement du volume) | cryptsetup luksFormat /dev/sdX |
| S3 | SSE-S3 ou SSE-KMS (côté serveur AWS) | Politique de bucket |
| MinIO | SSE-S3 (cle gérée par MinIO) | mc encrypt set sse-s3 myminio/nexus |
Chiffrement en transit¶
| Segment | Protocole | Configuration |
|---|---|---|
| Client → Reverse proxy | TLS 1.2+ | Certificat Let's Encrypt ou PKI interne |
| Reverse proxy → Nexus | HTTP | Réseau local isole (loopback ou VLAN) |
| Nexus → Registres publics | TLS 1.2+ | Vérification du certificat upstream |
| Nexus → PostgreSQL | TLS 1.2+ | sslmode=verify-full dans la config |
| Nexus → S3/MinIO | TLS 1.2+ | Endpoint HTTPS obligatoire |
Le segment reverse proxy → Nexus est en HTTP
Le trafic entre le reverse proxy et Nexus est en clair (HTTP). Ce segment doit etre isole sur un réseau local (loopback ou VLAN dedie) pour eviter l'écoute passive. Ne jamais exposer les ports Nexus (8081-8083) directement sur le réseau.