
Proxy bastion SSH à confiance zéro avec gestion des clés basée sur Vault, application des politiques RBAC, enregistrement complet des sessions et interface TUI d’administration pour un accès auditable à l’infrastructure de production.
Un bastion SSH auto-hébergé et durci avec gestion des clés basée sur Vault, application de politiques RBAC, enregistrement complet des sessions et une TUI d'administration interactive — conçu pour les équipes ayant besoin d'un accès auditable et zero-trust à l'infrastructure de production.
Les équipes d'ingénierie modernes ont besoin d'un moyen de donner aux développeurs l'accès minimum requis pour faire leur travail — ni plus, ni moins. La distribution traditionnelle des clés SSH est sujette aux erreurs : les clés sont partagées, oubliées sur les ordinateurs portables et révoquées des jours trop tard.
ZTTP résout ce problème en agissant comme la porte unique vers votre infrastructure :
Ordinateur portable du développeur
│
│ zttp
│ (Sous le capot : SSH sur le port 2224)
▼
┌─────────────────────────────────────────────────────────┐
│ Proxy ZTTP │
│ │
│ ① Porte d'authentification — TUI de connexion bcrypt/Argon2id │
│ ② Moteur RBAC — vérification de politique sensible à l'environnement │
│ ③ Récupération Vault — récupération éphémère de clé SSH │
│ ④ Pont — tunnel TCP transparent │
│ ⑤ Écrivain d'audit — enregistreur de trames ttyrec │
└──────────┬──────────────────────────────────────────────┘
│ ssh (IP privée, clé éphémère)
▼
Serveur cible
Services d'infrastructure (Docker Compose) :
.ttyrec avec des trames horodatéesServeur (hôte proxy) :
2224make (optionnel, mais recommandé)Développeur (client) :
ssh)git clone https://gitlab.com/Nihal799/zttp.git
cd zttp
cp .env.example .env
Modifiez .env et définissez au minimum :
PROXY_NODE_IP=<ip-publique-de-votre-serveur>
POSTGRES_PASSWORD=<un-mot-de-passe-fort>
VAULT_TOKEN=<un-jeton-vault-fort>
⚠️ Ne committez jamais votre fichier
.env. Il est listé dans.gitignore.
make docker-up
# ou directement :
docker compose -f deploy/docker-compose.yml up -d --build
make docker-ps
curl http://localhost:8080/healthz
make release PROXY_ADDR=<ip-de-votre-serveur>:2224
Cela compile en croisé les clients pour toutes les plateformes et met automatiquement à jour dist/install.sh et dist/install.ps1 avec l'URL correcte du serveur. Le conteneur Nginx les sert à http://<ip-de-votre-serveur>:8555/.
curl -fsSL http://<ip-du-proxy>:8555/install.sh | bash
irm http://<ip-du-proxy>:8555/install.ps1 | iex
Une fois installé, connectez-vous à la passerelle ZTTP :
zttp
# ou directement :
ssh -p 2224 <votre-nom-dutilisateur>@<ip-du-proxy>
Un écran de connexion terminal s'affichera. Après authentification, vous verrez une liste des serveurs auxquels vous êtes autorisé à accéder.
Toute la configuration se fait via des variables d'environnement (ou le fichier .env). Voir .env.example pour la référence complète.
ZTTP utilise un modèle basé sur les rôles. Chaque utilisateur se voit attribuer un rôle ; chaque rôle a une politique qui définit à quels environnements de serveurs il peut accéder.
Les rôles et les affectations de serveurs sont gérés via la console d'administration (voir ci-dessous). Le moteur RBAC effectue toutes les vérifications dans une seule requête PostgreSQL — il n'expose jamais pourquoi l'accès a été refusé au client (protection contre l'énumération).
Connectez-vous au serveur zttp-admin depuis le menu de la passerelle, ou connectez-vous avec un compte ayant le rôle security-admin.
La console d'administration fournit :
Toutes les actions administratives sont consignées dans
admin-actions.logdans le volume d'audit.
Toutes les sessions sont stockées dans le volume Docker zttp-audit-logs (/var/log/zttp/audit/ dans le conteneur).
security-adminCtrl+C pour revenir en arrière# Lister les enregistrements
sudo ls /var/lib/docker/volumes/zttp-audit-logs/_data/
# Lire un enregistrement avec ttyplay
sudo ttyplay /var/lib/docker/volumes/zttp-audit-logs/_data/<id-de-session>.ttyrec
# Lire le journal des actions administratives
sudo cat /var/lib/docker/volumes/zttp-audit-logs/_data/admin-actions.log
Prérequis : Go 1.25+, Docker (pour la compilation croisée)
# Compiler le proxy + CLI pour la plateforme actuelle
make build
# Compiler en croisé la CLI pour toutes les plateformes (Linux, macOS, Windows)
make release PROXY_ADDR=<ip-du-proxy>:2224
# Exécuter les tests
make test
# Exécuter le proxy localement (nécessite Postgres + Vault déjà en cours d'exécution)
make run-proxy
zttp/
├── cmd/
│ ├── proxy/ # Point d'entrée du serveur proxy
│ └── zttp/ # Point d'entrée du client CLI
├── db/
│ └── migrations/ # Migrations de schéma PostgreSQL
├── deploy/
│ ├── docker-compose.yml
│ ├── Dockerfile.proxy
│ └── vault-seed.sh # Remplit les clés SSH de test dans Vault
├── dist/
│ ├── install.sh # Script d'installation Linux/macOS
│ └── install.ps1 # Script d'installation Windows
├── internal/
│ ├── audit/ # Journalisation des actions administratives
│ ├── auth/ # Authentification utilisateur (bcrypt, verrouillage)
│ ├── cli/ # TUI du client CLI et logique de connexion
│ ├── config/ # Configuration basée sur l'environnement
│ ├── killswitch/ # Service gRPC kill-switch
│ ├── proxy/ # Proxy SSH, TUI de passerelle, TUI d'administration, pont
│ ├── rbac/ # Moteur de contrôle d'accès basé sur les rôles
│ ├── ratelimit/ # Limitation de débit par IP
│ ├── session/ # Suivi des sessions et stockage en base de données
│ └── vault/ # Client de clés SSH HashiCorp Vault
├── proto/ # Définitions de protocole gRPC
├── tools/
│ └── hashpw/ # Outil CLI : générer un hachage de mot de passe bcrypt
├── .env.example # Modèle de configuration
├── go.mod
└── Makefile
git checkout -b feat/votre-fonctionnalitémake testVeuillez ne pas committer :
.env ou tout fichier contenant des secretszttp à la racine est .gitignored)Ce projet est propriétaire. Tous droits réservés.
Conçu avec Go, PostgreSQL, HashiCorp Vault et Docker.
| Problème | Solution ZTTP |
|---|
| Clés SSH partagées sur les ordinateurs portables | Les clés vivent uniquement dans HashiCorp Vault — jamais sur disque |
| Aucune visibilité sur qui a fait quoi | Chaque frappe est enregistrée au format .ttyrec |
| Accès de production généralisé | Le moteur de politique basé sur les rôles applique des règles par environnement |
| Aucun moyen d'arrêter une session active | Point de terminaison gRPC kill-switch qui termine toute session en direct |
| Accès opaque pour les auditeurs | TUI d'administration avec lecture des sessions, journaux texte et journaux d'actions administratives |
| Service | Objectif |
|---|
zttp-proxy | Le bastion SSH (binaire Go) |
zttp-postgres | Base de données du plan de contrôle (utilisateurs, serveurs, politiques RBAC) |
zttp-vault | HashiCorp Vault — stocke les clés privées SSH |
zttp-nginx | Sert les installateurs CLI à /release/ |
zttp-init-audit | Conteneur à usage unique qui corrige les permissions des volumes |
| Variable | Défaut | Description |
|---|
PROXY_LISTEN_ADDR | 0.0.0.0:2222 | Adresse de liaison du proxy SSH |
HTTP_LISTEN_ADDR | 0.0.0.0:8080 | Adresse HTTP de vérification de santé |
GRPC_LISTEN_ADDR | 0.0.0.0:9090 | Adresse gRPC du kill-switch |
PROXY_NODE_IP | 127.0.0.1 | IP externe intégrée dans les binaires CLI |
DATABASE_URL | postgres://zttp:... | Chaîne de connexion PostgreSQL |
VAULT_ADDR | http://localhost:8201 | URL du serveur Vault |
VAULT_TOKEN | dev-root-token-zttp | Jeton racine Vault (dev uniquement — utilisez AppRole en production) |
MAX_FAILED_ATTEMPTS | 5 | Seuil de verrouillage |
LOCKOUT_DURATION | 15m | Durée du verrouillage de compte |
RATE_LIMIT_PER_MIN | 10 | Nombre maximal de tentatives de connexion par minute et par IP |
AUDIT_LOG_DIR | /var/log/zttp/audit | Chemin du répertoire d'enregistrement des sessions |
SOC_WEBHOOK_URL | (vide) | Webhook optionnel pour les alertes SOC |
| Rôle | Accès |
|---|
security-admin | Accès complet à tous les environnements + console d'administration |
sre-tier1 | Tous les environnements, y compris la production |
sre-tier2 | Uniquement staging et développement |
dev | Environnement de développement uniquement |
readonly | Environnement de développement, ensemble de commandes restreint |
| Option de menu | Description |
|---|
| Ajouter un utilisateur | Créer un nouvel utilisateur avec attribution de rôle |
| Ajouter un serveur | Enregistrer un serveur cible (nom d'hôte, IP, environnement, utilisateur SSH) |
| Gérer l'accès aux serveurs | Octroyer ou révoquer l'accès utilisateur à des serveurs spécifiques |
| Voir les utilisateurs | Lister tous les utilisateurs et leurs rôles |
| Voir les serveurs | Lister tous les serveurs enregistrés |
| Voir les journaux d'audit | Parcourir les sessions, rejouer les enregistrements, lire les journaux texte |
| [ Retour ] | Revenir à la passerelle de serveurs |
| Commande | Description |
|---|
make build | Compiler le proxy et la CLI pour la plateforme actuelle |
make release | Compiler en croisé les binaires CLI pour toutes les plateformes |
make release-docker | Compiler en croisé dans un conteneur Docker (évite les problèmes snap/WSL) |
make docker-up | Démarrer tous les services Docker Compose |
make docker-down | Arrêter tous les services et supprimer les volumes |
make docker-logs | Suivre les journaux du proxy |
make docker-ps | Afficher l'état des conteneurs |
make test | Exécuter tous les tests Go |
make migrate | Appliquer les migrations de base de données |
make seed | Remplir les données de développement |
make hashpw PW=motdepasse | Générer un hachage bcrypt pour le remplissage manuel de la base de données |
make clean | Supprimer les binaires compilés et le cache de compilation |
| Couche | Mécanisme |
|---|
| Transport | Toutes les connexions client sont SSH (chiffrées en transit) |
| Authentification | bcrypt (coût 12) / Argon2id — le texte en clair est structurellement interdit dans le schéma |
| Protection contre la force brute | Verrouillage de compte (5 tentatives / 15 min) + limiteur de débit par IP |
| Autorisation | Requête RBAC à JOIN unique — les refus sont toujours génériques (« Permission refusée ») |
| Gestion des secrets | Les clés privées SSH sont stockées exclusivement dans HashiCorp Vault, récupérées de manière éphémère |
| Piste d'audit | Enregistrement complet des frappes au format .ttyrec, journal admin immuable en ajout seul |
| Isolation des processus | Le proxy s'exécute en non-root (UID 65532) dans un conteneur distroless |
| Kill switch | Toute session en direct peut être terminée via gRPC sans redémarrer le proxy |