Déployer avec Docker
Quatre images, un binaire chacune, distroless (pas de shell, nonroot, glibc) :
| Image | Binaire | Rôle |
|---|---|---|
ghcr.io/obsign/obsign-proxy | obsign-proxy | la passerelle |
ghcr.io/obsign/obsign-ledger | obsign-ledger | scellement, ancrage, export de preuves |
ghcr.io/obsign/obsign-control | obsign-control | compilation, publication, export, console |
ghcr.io/obsign/obsign | obsign | vérificateur hors ligne (commodité, voir plus bas) |
Construites à chaque tag v* : multi-architecture (amd64/arm64), signées avec
cosign (sans clé), étiquetées avec le semver et le sha source exact. Vérifiez
avant d’exécuter :
cosign verify ghcr.io/obsign/obsign-proxy:1.0.0 \ --certificate-identity-regexp 'github.com/obsign/obsign' \ --certificate-oidc-issuer https://token.actions.githubusercontent.comglibc plutôt que musl statique, délibérément : les modules PKCS#11 sont
chargés avec dlopen, et un binaire entièrement statique ne peut pas héberger
la bibliothèque HSM d’un fournisseur.
L’image de la passerelle est une image de base
Section intitulée « L’image de la passerelle est une image de base »obsign-proxy enveloppe un serveur MCP qu’il lance en processus enfant :
l’image est donc livrée sans. Étendez-la :
FROM ghcr.io/obsign/obsign-proxy:1.0.0COPY --chown=nonroot:nonroot my-mcp-server /usr/local/bin/my-mcp-server# Config (signed bundles) is mounted, not baked: whoever can write the# identity bundle can mint identities.docker run -d \ -v ./config:/etc/obsign:ro \ -v obsign-wal:/var/lib/obsign/wal \ -p 127.0.0.1:8080:8080 \ my-gateway \ --policy /etc/obsign/policy-bundle.json \ --trusted-keys /etc/obsign/trusted-keys.json \ --identity-bundle /etc/obsign/identity-bundle.json \ --http 0.0.0.0:8080 \ --wal /var/lib/obsign/wal \ --env prod \ -- /usr/local/bin/my-mcp-serverPoints non négociables
Section intitulée « Points non négociables »Le volume du WAL doit honorer fsync. La garantie de la passerelle est
l’fsync avant transmission ; elle ne vaut que ce que vaut le volume qui la
porte. Un système de fichiers réseau qui acquitte les écritures avant qu’elles
ne soient durables (NFS en async, certains pilotes overlay) annule
silencieusement la garantie. Traitez le volume du WAL comme celui d’une base
de données.
Le ledger s’exécute dans un conteneur séparé, idéalement sur un hôte
séparé. Le conteneur de la passerelle reçoit le volume du WAL en
lecture-écriture et aucun matériel de clé ; le conteneur du ledger reçoit le
WAL en lecture seule et la clé (ou le HSM), et écrit son propre volume de
store. Ne donnez pas restart: always au ledger : il sort avec un code non
nul en cas de divergence, précisément pour que quelqu’un soit prévenu (voir
Alerter sur une divergence).
docker run --rm \ -v obsign-wal:/wal:ro \ -v obsign-store:/store \ -v ./seal-seed.hex:/run/secrets/seal-seed.hex:ro \ ghcr.io/obsign/obsign-ledger \ seal --wal /wal --chain-id <chain> --store /store \ --key /run/secrets/seal-seed.hex --key-id seal-prodLe port HTTP de la passerelle est en clair. Les jetons voyagent dans
l’en-tête Authorization : publiez donc le port uniquement sur la boucle
locale, jamais sur une adresse routable. Devant de vrais clients, terminez TLS
dans un reverse proxy : TLS devant la passerelle.
La console n’a pas d’authentification. Publiez son port sur la boucle locale ou sur un réseau privé uniquement (l’authentification de la console relève de la couche commerciale).
Les deux utilisateurs d’exécution sont nonroot (uid 65532). Les
répertoires hôtes pré-créés et montés en volumes doivent être accessibles en
écriture par cet uid.
Déployer les règles sur arguments (obsign-policy/2)
Section intitulée « Déployer les règles sur arguments (obsign-policy/2) »Le plan de contrôle émet le format de bundle /2 dès qu’un outil déclare
policy_args. Une passerelle non mise à niveau refuse un bundle /2 au
démarrage plutôt que d’appliquer silencieusement moins que ce que le bundle
énonce. L’ordre de bascule est fixe : mettre à niveau toutes les images de
passerelle d’abord, publier le premier bundle déclarant des arguments ensuite.
Une flotte qui ne déclare jamais d’arguments continue de recevoir du /1 et
n’a besoin de rien.
HSM (PKCS#11) et TPM
Section intitulée « HSM (PKCS#11) et TPM »Le module PKCS#11 du fournisseur est chargé à l’exécution avec dlopen :
montez le .so (et ce dont il a besoin) dans le conteneur du ledger et passez
--hsm-module :
docker run --rm \ -v obsign-wal:/wal:ro -v obsign-store:/store \ -v /usr/lib/softhsm:/usr/lib/softhsm:ro \ -v softhsm-tokens:/var/lib/softhsm/tokens \ -v ./hsm-pin:/run/secrets/hsm-pin:ro \ ghcr.io/obsign/obsign-ledger \ seal --wal /wal --chain-id <chain> --store /store \ --hsm-module /usr/lib/softhsm/libsofthsm2.so \ --hsm-key-label seal-prod --hsm-pin-file /run/secrets/hsm-pin \ --key-id seal-prodL’enrôlement TPM (obsign-tpm-enroll) a besoin du gestionnaire de ressources
du noyau (--device /dev/tpmrm0). C’est une cérémonie d’opérateur :
exécutez-le depuis l’arbre des sources sur l’hôte à enrôler, pas depuis un
conteneur à longue durée de vie.
Livraison en air-gap
Section intitulée « Livraison en air-gap »Le registre est une commodité, pas une dépendance :
# Connected side: pull by digest, save, hash.docker pull ghcr.io/obsign/obsign-proxy@sha256:<digest>docker save ghcr.io/obsign/obsign-proxy@sha256:<digest> -o obsign-proxy.tarsha256sum obsign-proxy.tar > obsign-proxy.tar.sha256
# Air-gapped side: verify the hash out of band, then load.sha256sum -c obsign-proxy.tar.sha256docker load -i obsign-proxy.tarLe digest voyage hors bande (il figure dans les notes de release signées) ; la vérification cosign a lieu du côté connecté, avant l’export.
L’image du vérificateur est une commodité
Section intitulée « L’image du vérificateur est une commodité »L’argument d’obsign verify est que l’auditeur le compile lui-même, depuis
les sources, et l’exécute sans réseau. L’image existe pour les pipelines CI
(conditionnement sur le code de sortie) ; ce n’est pas le canal par lequel on
remet quelque chose à un auditeur.
Démo locale
Section intitulée « Démo locale »docker compose up -d gateway consoledocker compose run --rm demo # drives the gateway, seals, verifies: exit 0L’image de démo (shell, forgeur de jetons, graine dans un fichier) est réservée à compose et n’est jamais publiée : le moyen de forger des jetons n’a rien à faire dans un artefact livré.