Référence API — APT Repo Manager¶
Table des matières¶
- Authentification
- Codes de réponse standard
- Endpoints par module
- Auth
- Packages
- Upload
- Import
- Sécurité
- SBOM
- Téléchargements
- Dashboard
- Distributions
- Paramètres
- Santé
- Exemples complets
- Intégration CI/CD
- Limites et rate limiting
Authentification¶
JWT (sessions interactives)¶
La majorité des endpoints requiert un token JWT transmis dans l'en-tête HTTP Authorization.
Obtenir un token :
TOKEN=$(curl -s -X POST http://localhost:8000/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"Admin1234!"}' | jq -r .access_token)
Utiliser le token :
API Tokens (CI/CD)¶
Pour les pipelines automatisés, utilisez un API token permanent au format repod_xxxxxxxxxx :
Les API tokens sont créés et gérés via les endpoints /auth/api-tokens (réservé aux admins).
Endpoints publics (sans authentification)¶
Les endpoints suivants sont accessibles sans token :
| Endpoint | Description |
|---|---|
POST /auth/token |
Connexion / obtention du JWT |
POST /auth/forgot-password |
Demande de réinitialisation de mot de passe |
POST /auth/reset-password |
Réinitialisation avec token reçu par e-mail |
GET /health |
Bilan de santé complet |
GET /health/live |
Sonde de vivacité |
GET /health/ready |
Sonde de disponibilité |
Codes de réponse standard¶
| Code | Signification |
|---|---|
200 OK |
Requête traitée avec succès |
201 Created |
Ressource créée avec succès |
204 No Content |
Succès sans corps de réponse |
400 Bad Request |
Paramètres ou corps de requête invalides |
401 Unauthorized |
Token absent, invalide ou expiré |
403 Forbidden |
Rôle insuffisant pour cette action |
404 Not Found |
Ressource introuvable |
409 Conflict |
Ressource déjà existante (doublon) |
422 Unprocessable Entity |
Erreur de validation des données |
429 Too Many Requests |
Limite de taux atteinte |
500 Internal Server Error |
Erreur côté serveur |
Endpoints par module¶
Auth (/auth)¶
POST /auth/token¶
Public. Connexion et obtention du JWT.
curl -s -X POST http://localhost:8000/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"Admin1234!"}'
Réponse :
GET /auth/me¶
Informations sur l'utilisateur actuellement connecté.
Réponse :
POST /auth/change-password¶
Changer son propre mot de passe.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/change-password \
-d '{"current_password":"Admin1234!","new_password":"NewPass5678!"}'
GET /auth/roles¶
Public. Lister les rôles disponibles.
GET /auth/users¶
Admin. Lister tous les utilisateurs.
POST /auth/users¶
Admin. Créer un nouvel utilisateur.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/users \
-d '{
"username": "jdupont",
"email": "jdupont@example.com",
"password": "SecurePass1!",
"roles": ["uploader"]
}'
PATCH /auth/users/{username}¶
Admin. Modifier un utilisateur existant.
curl -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/users/jdupont \
-d '{"roles":["uploader","auditor"]}'
DELETE /auth/users/{username}¶
Admin. Supprimer un utilisateur.
POST /auth/users/{username}/reset-password¶
Admin. Réinitialiser le mot de passe d'un utilisateur.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/users/jdupont/reset-password \
-d '{"new_password":"TempPass9!"}'
POST /auth/forgot-password¶
Public, rate-limité. Demander un e-mail de réinitialisation.
curl -X POST http://localhost:8000/auth/forgot-password \
-H "Content-Type: application/json" \
-d '{"email":"jdupont@example.com"}'
POST /auth/reset-password¶
Public, rate-limité. Réinitialiser le mot de passe avec le token reçu par e-mail.
curl -X POST http://localhost:8000/auth/reset-password \
-H "Content-Type: application/json" \
-d '{"token":"<reset_token>","new_password":"NewPass5678!"}'
GET /auth/api-tokens¶
Admin. Lister les API tokens existants.
POST /auth/api-tokens¶
Admin. Créer un API token.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/api-tokens \
-d '{"name":"gitlab-ci","roles":["uploader"]}'
Réponse :
Le token brut
repod_xxxxxxxxxxn'est affiché qu'une seule fois. Conservez-le immédiatement.
DELETE /auth/api-tokens/{token_id}¶
Admin. Révoquer un API token.
Packages (/packages, /artifacts)¶
GET /packages/¶
Lister les packages avec recherche et filtres.
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/packages/?q=nginx&distribution=jammy"
GET /artifacts/¶
Lister tous les artefacts.
GET /artifacts/{name}¶
Informations sur un package.
GET /artifacts/{name}/dependencies¶
Dépendances d'un package.
GET /artifacts/{name}/install¶
Commande d'installation d'un package.
GET /artifacts/{name}/{version}¶
Informations sur une version spécifique.
GET /artifacts/audit/logs¶
Auditor+. Consulter les journaux d'audit.
POST /artifacts/admin/sync-index¶
Maintainer+. Synchroniser l'index des packages.
Upload (/upload)¶
POST /upload/¶
Uploader+, rate-limité (20/min). Publier un fichier .deb.
| Champ formulaire | Type | Description |
|---|---|---|
file |
fichier | Fichier .deb à publier |
distribution |
string | Codename cible (ex. jammy) |
curl -X POST -H "Authorization: Bearer $TOKEN" \
-F "file=@mypackage_1.0.0_amd64.deb" \
-F "distribution=jammy" \
http://localhost:8000/upload/
Réponse (201) :
{
"name": "mypackage",
"version": "1.0.0",
"arch": "amd64",
"distribution": "jammy",
"status": "indexed"
}
Import (/import)¶
GET /import/search¶
Rechercher un package dans l'index APT.
| Paramètre | Type | Description |
|---|---|---|
q |
string | Terme de recherche |
limit |
int | Nombre max de résultats |
source_id |
string | Filtrer par source APT |
GET /import/resolve/{package_name}¶
Résoudre les dépendances en ligne pour un package.
POST /import/fetch¶
Uploader+, rate-limité (10/min). Importer un package depuis internet.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/import/fetch \
-d '{
"name": "nginx",
"version": "1.24.0",
"arch": "amd64",
"distribution": "jammy"
}'
POST /import/batch¶
Uploader+, rate-limité (5/min). Import en lot.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/import/batch \
-d '{
"packages": [
{"name":"nginx","version":"1.24.0","arch":"amd64","distribution":"jammy"},
{"name":"curl","version":"7.81.0","arch":"amd64","distribution":"jammy"}
]
}'
GET /import/sync-status¶
Statut de synchronisation de toutes les sources APT.
POST /import/sync¶
Maintainer+, rate-limité (3/min). Synchroniser toutes les sources APT.
GET /import/groups¶
Lister les groupes d'import.
DELETE /import/groups/{group_name}¶
Supprimer un groupe d'import.
POST /import/sync/{source_id}¶
Maintainer+. Synchroniser une source APT spécifique.
POST /import/sync-security¶
Maintainer+. Synchroniser les sources de sécurité.
GET /import/sync-schedule¶
Prochaine synchronisation planifiée.
Sécurité (/security)¶
GET /security/vulnerabilities¶
Lister les CVE sur l'ensemble des packages.
GET /security/packages-posture¶
Résumé de la posture de sécurité.
GET /security/packages/{name}/{version}/cve¶
CVE associées à une version de package.
GET /security/review-queue¶
Auditor+. Packages en attente de revue RSSI.
POST /security/packages/{name}/{version}/decide¶
Maintainer+. Rendre une décision sur les CVE d'un package.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/security/packages/nginx/1.24.0/decide \
-d '{"decision":"accepted","comment":"Risque accepté après analyse."}'
POST /security/packages/{name}/{version}/rescan¶
Maintainer+. Déclencher un nouveau scan de vulnérabilités.
curl -X POST -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/security/packages/nginx/1.24.0/rescan
POST /security/packages/{name}/{version}/quarantine¶
Maintainer+. Mettre un package en quarantaine.
curl -X POST -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/security/packages/nginx/1.24.0/quarantine
GET /security/clamav/status¶
Statut du moteur antivirus ClamAV.
POST /security/clamav/update¶
Maintainer+. Mettre à jour la base de signatures ClamAV.
SBOM (/sbom)¶
GET /sbom/export¶
Exporter le SBOM complet.
| Paramètre | Valeurs | Description |
|---|---|---|
format |
cyclonedx, spdx |
Format de sortie |
distribution |
codename | Filtrer par distribution |
# CycloneDX
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/sbom/export?format=cyclonedx&distribution=jammy" \
-o sbom.cdx.json
# SPDX
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/sbom/export?format=spdx&distribution=jammy" \
-o sbom.spdx.json
GET /sbom/{name}/{version}¶
SBOM d'un package spécifique.
| Paramètre | Valeurs | Description |
|---|---|---|
format |
cyclonedx, spdx |
Format de sortie |
arch |
ex. amd64 |
Architecture |
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/sbom/nginx/1.24.0?format=cyclonedx&arch=amd64" \
-o nginx-sbom.cdx.json
GET /sbom/preview¶
Aperçu du SBOM (limité).
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/sbom/preview?format=cyclonedx&distribution=jammy&limit=5"
Téléchargements (/downloads)¶
GET /downloads/stats¶
Statistiques de téléchargements.
| Paramètre | Valeurs | Description |
|---|---|---|
days |
7, 30, 90 |
Période |
Dashboard (/dashboard)¶
GET /dashboard/stats¶
Statistiques globales du dépôt.
GET /dashboard/history¶
Historique des événements.
Distributions (/distributions)¶
GET /distributions/¶
Lister les distributions disponibles.
GET /distributions/{codename}/packages¶
Packages présents dans une distribution.
POST /distributions/promote¶
Promouvoir un package vers une autre distribution.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/distributions/promote \
-d '{
"name": "nginx",
"version": "1.24.0",
"arch": "amd64",
"from_distribution": "jammy",
"to_distribution": "focal"
}'
POST /distributions/migrate¶
Migrer des packages entre distributions.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/distributions/migrate \
-d '{
"from_distribution": "focal",
"to_distribution": "jammy",
"packages": ["nginx","curl"]
}'
POST /distributions/init¶
Initialiser une nouvelle distribution.
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/distributions/init \
-d '{"codename":"noble","description":"Ubuntu 24.04 LTS"}'
Paramètres (/settings)¶
Tous les endpoints
/settingssont réservés aux admins.
GET /settings/¶
Lire la configuration complète (mots de passe masqués).
PATCH /settings/¶
Modifier la configuration.
curl -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/settings/ \
-d '{"retention_days": 90}'
POST /settings/test-webhook¶
Tester le webhook configuré.
GET /settings/gpg¶
Informations sur la clé GPG du dépôt.
POST /settings/gpg/generate¶
Générer une nouvelle clé GPG.
GET /settings/next-sync¶
Prochaine synchronisation planifiée.
POST /settings/test-ldap¶
Tester la connexion LDAP.
POST /settings/run-retention¶
Déclencher la politique de rétention manuellement.
POST /settings/test-email¶
Envoyer un e-mail de test.
Santé (/health)¶
GET /health¶
Public. Bilan de santé complet avec statut de tous les sous-systèmes.
Réponse :
GET /health/live¶
Public. Sonde de vivacité (renvoie toujours 200 si le service est démarré).
GET /health/ready¶
Public. Sonde de disponibilité (indique si le service est prêt à accepter des requêtes).
Exemples complets¶
Créer un utilisateur et lui attribuer un rôle¶
# 1. Obtenir un token admin
TOKEN=$(curl -s -X POST http://localhost:8000/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"Admin1234!"}' | jq -r .access_token)
# 2. Créer l'utilisateur
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/users \
-d '{
"username": "deployer",
"email": "deployer@example.com",
"password": "Deploy9876!",
"roles": ["uploader"]
}'
# 3. Créer un API token pour les pipelines CI
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/auth/api-tokens \
-d '{"name":"pipeline-deployer","roles":["uploader"]}' | jq -r .token
Publier et vérifier un package¶
# Upload
curl -X POST -H "Authorization: Bearer $TOKEN" \
-F "file=@myapp_2.0.0_amd64.deb" \
-F "distribution=jammy" \
http://localhost:8000/upload/
# Vérifier la présence
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/artifacts/myapp/2.0.0
# Vérifier les CVE
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/security/packages/myapp/2.0.0/cve
Importer un package depuis les dépôts upstream¶
# Recherche
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/import/search?q=curl&limit=5" | jq
# Résoudre les dépendances
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/import/resolve/curl | jq
# Import
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
http://localhost:8000/import/fetch \
-d '{"name":"curl","version":"7.81.0","arch":"amd64","distribution":"jammy"}'
Exporter le SBOM complet¶
# CycloneDX
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/sbom/export?format=cyclonedx&distribution=jammy" \
-o sbom-jammy.cdx.json
# SPDX
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/sbom/export?format=spdx&distribution=jammy" \
-o sbom-jammy.spdx.json
echo "SBOM exporté avec succès."
Intégration CI/CD¶
GitHub Actions — Publication d'un package¶
name: Publish package
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build .deb
run: make deb
- name: Upload to repod
env:
REPOD_TOKEN: ${{ secrets.REPOD_TOKEN }}
REPOD_URL: https://repo.example.com
run: |
curl -X POST "$REPOD_URL/upload/" \
-H "Authorization: Bearer $REPOD_TOKEN" \
-F "file=@mypackage_1.0.0_amd64.deb" \
-F "distribution=jammy"
GitLab CI — Publication d'un package¶
stages:
- build
- deploy
build:
stage: build
script:
- make deb
deploy:
stage: deploy
script:
- |
curl -X POST "$REPOD_URL/upload/" \
-H "Authorization: Bearer $REPOD_TOKEN" \
-F "file=@mypackage_1.0.0_amd64.deb" \
-F "distribution=jammy"
only:
- tags
Ajoutez
REPOD_TOKENetREPOD_URLdans les variables CI/CD de votre projet GitLab.
Import automatisé depuis upstream¶
#!/usr/bin/env bash
set -euo pipefail
REPOD_URL="https://repo.example.com"
REPOD_TOKEN="${REPOD_TOKEN}"
DISTRIBUTION="jammy"
PACKAGES=("nginx" "curl" "openssl")
for pkg in "${PACKAGES[@]}"; do
echo "Importation de $pkg..."
curl -s -X POST -H "Authorization: Bearer $REPOD_TOKEN" \
-H "Content-Type: application/json" \
"$REPOD_URL/import/fetch" \
-d "{\"name\":\"$pkg\",\"arch\":\"amd64\",\"distribution\":\"$DISTRIBUTION\"}"
done
Limites et rate limiting¶
Certains endpoints sont protégés par des limites de taux pour éviter les abus.
| Endpoint | Limite |
|---|---|
POST /upload/ |
20 requêtes / minute |
POST /import/fetch |
10 requêtes / minute |
POST /import/batch |
5 requêtes / minute |
POST /import/sync |
3 requêtes / minute |
POST /auth/forgot-password |
Rate-limité (non divulgué) |
POST /auth/reset-password |
Rate-limité (non divulgué) |
En cas de dépassement, le serveur répond avec 429 Too Many Requests. Attendez la durée indiquée dans l'en-tête Retry-After avant de relancer la requête.
Niveaux de rôle¶
Les rôles sont cumulatifs (un rôle supérieur inclut les droits des rôles inférieurs) :
| Rôle | Droits |
|---|---|
viewer |
Lecture seule |
uploader |
Viewer + publication et import de packages |
auditor |
Uploader + accès aux journaux et à la file de revue sécurité |
maintainer |
Auditor + synchronisation, quarantaine, décisions CVE |
admin |
Tous les droits, gestion des utilisateurs et de la configuration |