Formats de paquets¶
Repod héberge sept formats de paquets derrière un backend unique, un
modèle RBAC unique, un journal d'audit unique, et un pipeline de
sécurité unique. Cette page explique comment les différents formats se
rapportent les uns aux autres et au commutateur de paquets OS
(REPO_FORMAT) décrit dans Architecture.
Deux groupes indépendants¶
Les paquets OS — .deb, .rpm, .apk — sont sélectionnés par la
variable d'environnement REPO_FORMAT au démarrage. Une instance sert
exactement les formats de paquets OS pour lesquels elle est configurée,
en utilisant l'outillage de dépôt natif pour chacun (reprepro,
createrepo_c, apk index).
Les paquets d'outils de build — Maven, PyPI, npm — et le registre
de conteneurs OCI fonctionnent aux côtés de quel que soit le
REPO_FORMAT actif, indépendamment de lui. Ils sont toujours
disponibles ; il n'y a pas de variable d'environnement pour les activer
ou les désactiver.
| Format | Client natif | Dépôts/namespaces |
|---|---|---|
| APT | apt install |
Ensemble fixe de codenames de distribution |
| RPM | dnf install / zypper install |
Ensemble fixe de codenames de distribution |
| APK | apk add |
Ensemble fixe de codenames de distribution |
| Maven | mvn deploy / mvn dependency:get |
Créé au premier deploy réussi |
| PyPI | pip install / twine upload |
Créé au premier upload réussi |
| npm | npm publish / npm install |
Créé au premier publish réussi |
| OCI (Docker) | docker push / docker pull |
Créé au premier push réussi |
Les formats de paquets OS utilisent une liste fixe de distributions
gérée par un administrateur (par exemple jammy, almalinux9). Les
quatre formats plus récents utilisent à la place un modèle de dépôt
dynamique — plus proche du fonctionnement de Docker Hub ou d'un
registre npm privé : la première publication réussie vers un nom de
dépôt le crée, sans pré-enregistrement requis. L'accès à un dépôt
spécifique peut tout de même être restreint par la suite (voir
Rôles & permissions).
Comment chaque format dynamique se rattache à son propre dépôt¶
Maven résout le chemin de coordonnées GAV standard
(group:artifact:version) —
{groupId avec les points remplacés par des slashes}/{artifactId}/{version}/{artifactId}-{version}[-{classifier}].{extension}
— contre le dépôt, exactement comme mvn deploy/gradle publish
l'envoient déjà. Un seul deploy publie à la fois un .pom et un
.jar (ou .war, .aar, …) pour la même version ; Repod les suit
comme des entrées séparées afin qu'aucune n'écrase l'autre. Les
checksums client (.sha1/.md5) et maven-metadata.xml sont acceptés
mais jamais pris pour argent comptant — Repod régénère toujours les
deux à partir des octets d'artefact qu'il a réellement stockés. Les
versions SNAPSHOT sont rejetées au moment de la publication — seules
les versions release sont acceptées.
PyPI implémente la Simple Repository API (PEP 503) pour
pip install et le protocole d'upload multipart historique pour
twine upload — le même protocole qu'upload.pypi.org utilise
lui-même, sans outillage client personnalisé nécessaire. Les noms de
projet sont normalisés selon PEP 503 (mis en minuscules, les suites de
-/_/. réduites à un seul -) avant la correspondance, de sorte
que My_Project et my-project résolvent vers le même projet.
npm implémente le protocole réel du registre npm — GET de
packument, GET de tarball, et publication PUT avec le tarball
attaché en base64 dans le corps de la requête, la même forme
qu'envoie npm publish sur le fil. L'authentification réutilise
directement le mécanisme de token de l'API REST propre à Repod
(Authorization: Bearer <token>) plutôt qu'un flux de connexion
séparé — collez un token API Repod dans .npmrc et npm publish/
npm install fonctionnent immédiatement, sans étape npm login. Les
paquets scopés (@scope/name) sont pris en charge à la fois pour la
publication et l'installation.
OCI (images Docker/conteneurs) repose sur un registre
Zot embarqué. docker push/docker pull
communiquent directement avec Zot via le protocole standard Docker
Registry v2 — Repod lui-même ne se trouve jamais dans ce chemin de
données, seulement dans l'émission du token Bearer de courte durée que
Zot valide. Voir Registre de conteneurs
pour le flux d'authentification et les détails de déploiement.
Le même pipeline, pour chaque format¶
Quel que soit le format sous lequel un paquet arrive, il traverse la même séquence avant de devenir servable :
Upload / push / publish reçu
│
▼
Validation du format
▼
Scan antivirus
▼
Analyse CVE + enrichissement EPSS/KEV
▼
Décision de politique — publication, ou mise en attente pour revue
▼
Publié — ou en attente dans la file de revue RSSI
C'est délibéré : une CVE Critique dans un wheel Python ou une image de
conteneur est exactement aussi dangereuse que dans un .deb, et Repod
la traite ainsi. Il n'existe pas de chemin « allégé » pour les formats
plus récents qui sauterait le scan — voir
Pipeline de sécurité pour la décomposition
complète.
Pour une image de conteneur, l'antivirus et le scan CVE s'exécutent
directement contre les blobs de couche bruts de l'image (chaque couche
n'est qu'un tar.gz, scanné de la même manière qu'une archive ar
d'un .deb ou une archive cpio d'un .rpm le sont déjà — sans
étape d'extraction manuelle du système de fichiers). Grype détecte
automatiquement l'écosystème langage/OS depuis l'artefact lui-même
pour Maven, PyPI, npm et OCI, de sorte qu'aucune intégration CVE par
format supplémentaire n'a été nécessaire au-delà de le pointer vers le
bon fichier.
Épinglage de digest à l'import : importer une image depuis un registre public résout le tag demandé vers son digest de manifeste une seule fois, et chaque étape ultérieure — scan, décision de revue, publication — opère sur ce digest exact et immuable, jamais à nouveau sur le tag. Un tag peut être repointé vers un contenu différent plus tard ; la décision de revue enregistrée par votre équipe ne le suit jamais silencieusement.
Scan CVE des dépendances (Maven, PyPI, npm)¶
Grype scanne les octets propres d'un artefact — le .jar compilé, le
wheel, le tarball. Il n'a aucune visibilité sur les dépendances
déclarées de cet artefact, qui sont résolues séparément au moment de
la construction d'un consommateur (npm install, mvn/gradle
résolvant une plage de versions, pip install). Une dépendance
vulnérable nommée dans package.json, le bloc <dependencies> d'un
.pom, ou les métadonnées requires_dist d'un wheel/sdist était donc
invisible pour le pipeline CVE de Repod.
Une seconde vérification indépendante comble cette lacune : Repod extrait les dépendances directes déclarées (pas de résolution transitive — un parcours complet de l'arbre de dépendances nécessiterait soit un véritable résolveur semver, soit un lockfile embarqué, dont aucun n'est porté par un artefact publié) et interroge OSV.dev par nom de paquet, par écosystème (npm, Maven, PyPI). La recherche se fait par nom uniquement, pas par la plage de version déclarée — délibérément sur-inclusif, puisque restreindre par une plage non résolue risque davantage un faux négatif qu'un résultat large ne risque du bruit ; un réviseur humain juge si la version réellement utilisée est vraiment affectée.
Une découverte de dépendance qui enfreint votre politique CVE est acheminée vers la même file de revue qu'une découverte dans le code propre du paquet — avec une différence : une politique qui bloquerait autrement une correspondance de dépendance est plafonnée à review à la place, jamais un rejet pur et simple. Contrairement à une CVE dans les octets propres du paquet, une correspondance de dépendance par nom seul est un signal plus bruyant (une part significative se révèle déjà corrigée en amont), elle est donc signalée pour un jugement humain plutôt que de bloquer la publication d'office. Une découverte de dépendance ne dégrade ni ne remplace jamais un verdict plus strict déjà atteint en scannant les octets propres du paquet.
Cette couverture est peuplée automatiquement pour la publication/le
deploy natif (npm publish, mvn deploy via le .pom,
twine upload) et pour l'import validé depuis les registres publics
ci-dessous, puisque chacun d'entre eux porte ou récupère déjà le
manifeste de dépendances. Un upload manuel brut sans métadonnées de
dépendance associées n'a rien à scanner pour cette vérification.
Protocoles natifs, pas une API personnalisée¶
Chaque format parle le protocole amont réel que son écosystème utilise
déjà. mvn deploy, pip install / twine upload, npm publish, et
docker push / docker pull fonctionnent tous contre Repod
exactement comme ils le feraient contre Maven Central, PyPI,
npmjs.org, ou Docker Hub — pointés vers votre URL Repod à la place,
avec vos identifiants Repod. Il n'y a rien à installer côté client au
delà de l'outil que votre équipe utilise déjà.
Voir Configuration client pour la configuration APT/RPM/Maven/PyPI/npm et Registre de conteneurs pour Docker.
Importer depuis des sources publiques¶
Plutôt que d'exiger que chaque artefact soit construit et poussé manuellement, trois des quatre formats dynamiques prennent également en charge l'import validé : pointez Repod vers un paquet sur Maven Central, PyPI, npmjs.org, ou une image Docker Hub publique, et il télécharge, scanne, et publie (ou met en file d'attente pour revue) cet artefact exact — sans jamais contourner le pipeline de sécurité. Il s'agit du même mécanisme déjà utilisé pour miroiter les avis de sécurité amont pour les paquets OS, étendu aux formats plus récents.
Chacun de Maven/PyPI/npm/OCI peut atteindre le stockage de Repod de
trois manières, et les trois passent par le pipeline de validation
identique décrit ci-dessus : le protocole de publication/deploy natif
propre au format (mvn deploy, twine upload, npm publish,
docker push), un upload manuel authentifié pour un artefact que vous
possédez déjà sur disque, ou un import validé depuis le registre public
du format. Aucun chemin ne saute le scan pour gagner du temps — la
seule différence entre eux est la provenance des octets.