Candidate 3.5.0

This commit is contained in:
Siphonight 2026-07-05 12:56:03 +02:00
parent c03d254f90
commit db103dab71
7 changed files with 352 additions and 78 deletions

View File

@ -4,7 +4,7 @@ FROM alpine:3.20.0 AS monosphere-builder
#Setting default settings, please change them at run
ARG MONOSPHERE_VERSION="3.4.11 Alpha"
ARG MONOSPHERE_VERSION="3.5.0 Alpha"
#Defining build settings
@ -67,6 +67,7 @@ ADD server_menu.sh /opt/public/scripts/
ADD admin_menu.sh /opt/public/scripts/
ADD authorized_servers.txt /opt/public/servers/
ADD admin_rights.txt /opt/public/rights/
ADD transfer_rights.txt /opt/public/rights/
ADD bastion_users.txt /root/scripts/users/
ADD sshd_config /etc/ssh/
@ -77,6 +78,12 @@ COPY --from=monosphere-builder /usr/local/bin/ttyrec /usr/local/bin/ttyrec
COPY --from=monosphere-builder /usr/local/bin/ttytime /usr/local/bin/ttytime
#Creating transfer logs directory
RUN mkdir -p /var/log/monosphere && \
touch /var/log/monosphere/transfers.log && \
chmod 777 /var/log/monosphere && \
chmod 666 /var/log/monosphere/transfers.log
#Activating scripts ;
RUN chmod 644 /etc/ssh/sshd_config && \
chown -R root:root /root/scripts && \

View File

@ -42,7 +42,10 @@ Voici une liste des différentes fonctionnalités déjà en place sur le bastion
- Support pour la connexion par clés SSH et mots de passe sur les hôtes distants.
- Sessions enregistrées et visionnables par les administrateurs du bastion ayant les autorisation appropriées.
- Support pour l'execution de scripts personalisés au lancement du conteneur.
- Recherche possible par nom de serveur distant dans la liste des serveurs du menu de connexion. (utile en cas de plusieurs serveurs configurés).
- Recherche possible par nom de serveur distant dans la liste des serveurs du menu de connexion (pratique pour les grandes flottes).
- Transfert de fichiers en une commande vers les serveurs distants via `push_file`/`retrieve_file` (non-interactif, sans stockage intermédiaire).
- Contrôle des droits de transfert par serveur, gérable par les administrateurs en temps réel.
- Journalisation complète de tous les transferts (utilisateur, serveur, fichier, taille, statut).
## Pourquoi choisir ce bastion ?
@ -58,20 +61,23 @@ Voici une liste des différentes fonctionnalités déjà en place sur le bastion
Ci-dessous une liste non exhaustive des objectifs des prochaines mises à jour du projet:
- [ ] Ajouter une option pour le transfert de fichiers au travers du bastion vers les machines distantes.
- [x] Ajouter le transfert de fichiers non-interactif au travers du bastion (`push_file`/`retrieve_file`).
- [x] Ajouter une option de recherche d'hôtes distants dans la liste des serveurs.
- [ ] Ajouter une option sous forme de variable d'environnement pour fournir au bastion les clés d'hôtes des machines distantes. (avec un mode confiance, strict ou test par exemple)
- [ ] Ajouter le support pour un serveur LDAP. (Objectif sur le long terme)
- [ ] Ajouter un système de mise à jour automatique dans le conteneur, évitant ainsi les redéploiements.
- [x] Ajouter la possibilité de revenir dans le menu des serveurs après une déconnexion d'une machine distante.
- [ ] Ajouter un système de cluster avec master/slave et synchronisation entre les nodes.
- [ ] Ajouter une option de gestion des droits de transfert par groupes d'utilisateurs.
- [ ] Support du chiffrement de bout en bout pour les transferts de fichiers sensibles.
- [x] Améliorer le système de journalisation du déploiement du bastion, avec les erreurs de déploiement affichées lors de la connexion des utilisateurs internes.
- [x] Ajouter un menu d'administration et de gestion lors de la connexion des utilisateurs internes du bastion.
- [x] Créer des rôles administrateur/inspecteur avec des droits différents au sein du bastion.
Correction en cours pour les bugs ci dessous :
Corrections de la version 3.5.0 :
Aucun bug n'a été détecté dans les configuration et scripts actuels du bastion, ou ces derniers ont bien été corrigés.
- [x] Correction de la récursion infinie dans le visionnage des sessions (`sessions_viewer`).
- [x] Correction du filtre utilisateur dans le menu d'administration (typo `user_map` → `users_map`, `user_counter` → `users_counter`).
Veuillez signaler tout problème rencontré en envoyant un email à l'adresse "**<crossghostmansiphonight@gmail.com>**", détaillant le problème ainsi que le contexte entourant le constat de ce dernier.
@ -126,7 +132,8 @@ docker run -d -p 22:22 \
-v /datasets/monosphere-bastion/servers:/opt/public/servers \
-v /datasets/monosphere-bastion/custom-scripts:/opt/custom/scripts \
-v /datasets/monosphere-bastion/users:/root/scripts/users \
-v /datasets/monosphere-bastion/admin_rights:/opt/public/rights \
-v /datasets/monosphere-bastion/rights:/opt/public/rights \
-v /datasets/monosphere-bastion/logs:/var/log/monosphere \
-p "22:22" \
--name monosphere-bastion siphonight/monosphere-bastion:latest
```
@ -149,7 +156,8 @@ services:
- /datasets/monosphere-bastion/servers:/opt/public/servers
- /datasets/monosphere-bastion/custom-scripts:/opt/custom/scripts
- /datasets/monosphere-bastion/users:/root/scripts/users
- /datasets/monosphere-bastion/admin_rights:/opt/public/rights
- /datasets/monosphere-bastion/rights:/opt/public/rights
- /datasets/monosphere-bastion/logs:/var/log/monosphere
ports:
- 22:22
restart: unless-stopped
@ -172,7 +180,8 @@ A noter que mettre la valeur à "1" pour **PASSWORD_AUTH** ne générera pas de
| **/opt/public/servers** | Le répertoire doit contenir un fichier nommé "**authorized_servers.txt**", contenant les autorisations de connexion et la liste des informations de machines distantes. Si vous utilisez l'authentification par clés privés ou par mots de passe pré-renseignés pour la connexion aux hôtes distants vous devez également ajouter les fichiers de ces dernières dans ce même répertoire. | *Ce fichier est ce qui vas gérer les droits accordés aux comptes sur les différents serveurs distants en temps réel. Une modification du fichier entrainera donc directement une modification au niveau des droits de connexion des utilisateurs, et des serveurs auquels le bastion permettra la connexion.* |
| **/opt/custom/scripts** | Ce répertoire doit contenir les scripts personnalisés de l'utilisateur, tous avec l'extension ".sh". Ces derniers seront exécutés avec le compte root au lancement du conteneur. | *Ces scripts peuvent servir à personnaliser plus amplement le conteneur du bastion, en modifiant par exemple la bannière en temps réel ou bien en changeant les paramètres du bastion qui ne sont pas disponibles avec une modification par variables d'environnement ou volumes.* |
| **/root/scripts/users** | Un fichier nommé "**bastion_users.txt**" contenant la liste des utilisateurs et de leurs paramètres de configuration. La syntaxe exacte de ce fichier est précisée plus bas dans la section "**Ajout d'utilisateurs**". Si vous activez l'option pour l'authentification par clé, vous devez également placer ici les dossiers aux noms des utilisateurs ajoutés ayant le contenu de leur répertoire "**.ssh**" avec les fichiers des clés publiques de connexion à l'utilisateur. | *Grace à ces paramètres, il est possible d'utiliser ce conteneur bastion de manière 100% stateless, car le redéployer en utilisant la même configuration et les mêmes fichiers permet de répliquer les mêmes comportements.* |
| **/opt/public/rights** | Ce répertoire doit contenir un fichier nommé "**admin_rights**", complété avec les droits administratifs sur le bastion et des utilisateurs auquels ces droits sont accordés. | *Les droits inscrits dans ce fichier sont mis à jour en temps réels. Veuillez vous assurer que ces derniers sont corrects et attribués aux administrateurs souhaités.* |
| **/opt/public/rights** | Ce répertoire doit contenir les fichiers "**admin_rights.txt**" (droits d'administration) et "**transfer_rights.txt**" (droits de transfert). | *Les droits inscrits dans ces fichiers sont mis à jour en temps réel. Veuillez vous assurer que ces derniers sont corrects et attribués aux utilisateurs et administrateurs souhaités.* |
| **/var/log/monosphere** | Le fichier "**transfers.log**" est créé automatiquement. | *Répertoire contenant les logs de transfert de fichiers. Accessible en consultation depuis le menu admin.* |
A noter que les droits mis sur les fichiers et dossiers configurés dans ces volumes ne sont pas importants, car ces derniers sont adaptés lors du déploiement du conteneur bastion.
@ -244,6 +253,7 @@ Explication des différents droits d'administration disponibles :
- **sessionswatch_admins** : Ce droit permet aux administrateurs le possédant de lire et visionner les sessions de connexion de tout les utilisateurs et administrateurs du bastion.
- **serverscontrol_admins** : Ce droit donne la possibilité de modifier les accès des utilisateurs et administrateurs du bastion aux hôtes distants, ainsi que les méthodes d'authentification et la configuration des serveurs distants.
- **adminscontrol_admins** : Ce droit permet de modifier l'attribution des autres droits. Un administrateur possédant ce dernier peut de ce fait gérer les privilèges des autres administrateurs du bastion, *y compris lui même*.
- **transfercontrol_admins** : Ce droit permet de gérer les droits de transfert de fichiers des utilisateurs du bastion. Un administrateur possédant ce droit peut éditer le fichier `transfer_rights.txt` pour autoriser ou restreindre les transferts vers les serveurs distants.
Dans l'exemple ci dessus, l'administrateur "bastion" à le droit de lire les sessions de connexion mais également de modifier les paramètres des connexions et accès aux serveurs distants ainsi que de donner ou de retirer des droits aux autres administrateurs du bastion. L'administrateur "vieweradmin" quant à lui n'a qu'un droit de lecture des sessions du bastion, et ne pourra pas effectuer de modifications.
@ -376,6 +386,50 @@ Si vous souhaitez vous connecter sur la même machine distante mais avec un util
A savoir qu'il est également possible d'utiliser des noms de domaine DNS à la place d'une adresse IP, mais prenez en compte le fait que la résolution de nom se fera au niveau du bastion et non du client.
### Transfert de fichiers (non-interactif)
Depuis la version 3.5.0, le bastion Monosphere supporte le transfert de fichiers vers les serveurs distants via des commandes SSH non-interactives. Aucun menu interactif n'est nécessaire, le transfert s'effectue directement depuis votre machine en une seule commande.
#### Prérequis
- Vous devez être autorisé à vous connecter au serveur distant (présent dans `authorized_servers.txt`).
- Vous devez avoir les droits de transfert pour ce serveur (configurés dans `transfer_rights.txt`, ou fichier absent = autorisé).
- Le bastion doit avoir accès au serveur distant (clé SSH ou mot de passe préconfiguré dans `authorized_servers.txt`).
#### Push — Envoyer un fichier vers un serveur distant
Depuis votre machine locale, envoyez un fichier directement vers un serveur distant à travers le bastion :
```bash
cat application.conf | ssh bastion_admin@bastion 'push_file serveur-prod /etc/app/application.conf'
```
Le fichier est transféré en une étape : il traverse le bastion et atterrit directement sur le serveur cible. Aucun stockage temporaire sur le bastion.
**Exemple concret :** Envoyer une archive de backup :
```bash
tar czf - /home/user/documents | ssh admin@bastion 'push_file serveur-backup /backups/documents-$(date +%F).tar.gz'
```
#### Pull — Récupérer un fichier depuis un serveur distant
```bash
ssh bastion_admin@bastion 'retrieve_file serveur-prod /var/log/app/error.log' > error.log
```
Le fichier est lu depuis le serveur distant et écrit sur stdout. Redirigez-le vers un fichier local.
**Exemple concret :** Récupérer plusieurs fichiers en une passe :
```bash
for f in access.log error.log audit.log; do
ssh admin@bastion "retrieve_file serveur-prod /var/log/nginx/\$f" > "./logs/\$f"
done
```
#### Journalisation
Tous les transferts (push, retrieve) sont horodatés et journalisés dans `/var/log/monosphere/transfers.log` avec l'utilisateur, le serveur cible, le fichier, la taille et le statut. Les administrateurs peuvent consulter ces logs depuis le menu admin (option `logs`).
### Scripts personnalisés
Vous pouvez ajouter des scripts personnalisés qui seront exécutés au démarrage du conteneur. Placez vos scripts dans le répertoire **/opt/custom/scripts/**.
@ -411,6 +465,7 @@ Ne modifiez jamais ces paramètres cela pourrait provoquer des problèmes de sé
- **admin_menu.sh** : Script permettant aux administrateurs d'exercer leurs droits au travers d'un menu controllé en fonction de leurs autorisations sur le bastion.
- **admin_rights.txt** : Liste des droits administratifs sur le bastion et ses ressources, exclusive aux administraturs du bastion.
- **transfer_rights.txt** : Liste des droits de transfert de fichiers par serveur, permettant de controler quels utilisateurs peuvent transferer des fichiers vers quels serveurs distants.
- **authorized_servers.txt** : Liste des utilisateurs autorisés et des serveurs correspondants.
- **bastion_users.txt** : Liste servant à générer les utilisateurs et administrateurs du bastion et contenant leurs paramètres de création.
- **Dockerfile** : Le fichier Dockerfile pour construire l'image Monosphere Bastion.
@ -574,6 +629,34 @@ Veuillez à ce que ce fichier ne comporte pas d'erreurs, ce dernier étant appli
Référez vous à la partie [Ajout d'administrateurs](#ajout-dadministrateurs) pour plus d'informations.
### Gestion des droits de transfert
Depuis la version 3.5.0, il est possible de controler quels utilisateurs peuvent transferer des fichiers vers quels serveurs distants.
Pour modifier ces droits, connectez-vous avec un administrateur disposant de la permission "transfercontrol_admins" et sélectionnez l'option "Gestion_des_droits_de_transfert" :
```text
@@@@@@@@@@[Welcome to the Monosphere bastion]@@@@@@@@@@
[...]
Veuillez sélectionner une option d'administration :
1) Gestion_des_droits_de_transfert
2) ...
Votre choix (1-X): 1
```
Le fichier `transfer_rights.txt` se trouve dans `/opt/public/rights/`. Son format est le suivant :
```text
# Format: nom_serveur user1,user2,...
# Les utilisateurs listés peuvent transferer des fichiers vers ces serveurs.
serveur1 alice,bob
serveur2 *
```
- Si le fichier est vide ou absent, **tous les utilisateurs** autorisés (via `authorized_servers.txt`) peuvent transferer des fichiers (comportement par défaut).
- Le caractère `*` permet d'autoriser **tous les utilisateurs** pour un serveur donné.
- Les modifications sont appliquées en temps réel, sans redémarrage du conteneur.
### Codes d'erreurs lors du lancement du bastion
Si lors du déploiement du bastion vous obtenez des messages indiquant "[ NOOK ] Code XX", veuillez consulter cette section, elle détaille la signification de chacun d'entre eux.

View File

@ -1,5 +1,10 @@
#!/bin/bash
if [[ -n ${SSH_ORIGINAL_COMMAND} ]]; then
bash /opt/public/scripts/server_menu.sh
exit $?
fi
function secure_file_editor() {
File_Path="${*}"
echo -e "\n=====SECURE=FILE=EDITOR====="
@ -37,62 +42,65 @@ function secure_file_editor() {
}
function sessions_viewer() {
echo -e "Ci dessous les utilisateurs disponibles sur le bastion.\nVeillez sélectionner celui dont vous souhaitez visionner les accès :"
Available_Users=$(find /home/. -maxdepth 1 -type d | grep -v "\.$" | cut -d "/" -f 4)
users_counter=0
declare -A users_map
while read -r line; do
user="${line}"
users_map[${users_counter}]="${user}"
echo "${users_counter}) ${user}"
users_counter=$((users_counter + 1))
done <<<"${Available_Users}"
echo "${users_counter}) Tapez 'quit' ou ${users_counter} pour revenir au menu précédent."
read -r -p "Votre choix (0-${users_counter}): " choice
if [[ ${choice} == "quit" ]] || [[ ${choice} == "${users_counter}" ]]; then
main_menu
elif [[ -z ${choice} ]] || [[ -z ${users_map[${choice}]} ]]; then
clear
echo "Sélection invalide."
else
local selected_option
selected_option="${users_map[${choice}]}"
while true; do
Available_Sessions=$(find /home/"${selected_option}"/. -maxdepth 1 -type f -name "*.ttyrec" | grep -v "\.$" | cut -d "/" -f 5)
echo "Sélectionnez une session de cet utilisateur que vous souhaitez visionner :"
sessions_counter=1
declare -A sessions_map
while read -r line; do
session_name="${line}"
sessions_map[${sessions_counter}]="${session_name}"
echo "${sessions_counter}) ${session_name}"
sessions_counter=$((sessions_counter + 1))
done <<<"${Available_Sessions}"
echo "${sessions_counter}) Tapez 'quit' ou ${sessions_counter} pour vous revenir au choix d'utilisateur."
read -r -p "Votre choix (1-${sessions_counter}): " choice
if [[ ${choice} == "quit" ]] || [[ ${choice} == "${sessions_counter}" ]]; then
sessions_viewer
elif [[ -z ${choice} ]] || [[ -z ${sessions_map[${choice}]} ]]; then
clear
echo "Sélection invalide."
else
local selected_session
selected_session="${sessions_map[${choice}]}"
ttyplay /home/"${selected_option}"/"${selected_session}"
fi
done
fi
while true; do
sessions_viewer
done
echo -e "Ci dessous les utilisateurs disponibles sur le bastion.\nVeillez sélectionner celui dont vous souhaitez visionner les accès :"
Available_Users=$(find /home/. -maxdepth 1 -type d | grep -v "\.$" | cut -d "/" -f 4)
users_counter=0
declare -A users_map
while read -r line; do
user="${line}"
users_map[${users_counter}]="${user}"
echo "${users_counter}) ${user}"
users_counter=$((users_counter + 1))
done <<<"${Available_Users}"
echo "${users_counter}) Tapez 'quit' ou ${users_counter} pour revenir au menu précédent."
read -r -p "Votre choix (0-${users_counter}): " choice
if [[ ${choice} == "quit" ]] || [[ ${choice} == "${users_counter}" ]]; then
return
elif [[ $(echo "${choice}" | cut -c1-1) == "f" ]]; then
filter=$(echo "${choice}" | cut -c2-)
echo "=====Résultats du filtre====="
for idx in "${!users_map[@]}"; do
if [[ ${users_map[${idx}]} == *"${filter}"* ]]; then
echo "${idx}) ${users_map[${idx}]}"
fi
done
read -r -p "Votre choix (0-${users_counter}) : " choice
elif [[ -z ${choice} ]] || [[ -z ${users_map[${choice}]} ]]; then
clear
echo "Sélection invalide."
else
local selected_option="${users_map[${choice}]}"
while true; do
Available_Sessions=$(find /home/"${selected_option}"/. -maxdepth 1 -type f -name "*.ttyrec" | grep -v "\.$" | cut -d "/" -f 5)
echo "Sélectionnez une session de cet utilisateur que vous souhaitez visionner :"
sessions_counter=1
declare -A sessions_map
while read -r line; do
session_name="${line}"
sessions_map[${sessions_counter}]="${session_name}"
echo "${sessions_counter}) ${session_name}"
sessions_counter=$((sessions_counter + 1))
done <<<"${Available_Sessions}"
echo "${sessions_counter}) Tapez 'quit' ou ${sessions_counter} pour revenir au choix d'utilisateur."
read -r -p "Votre choix (1-${sessions_counter}): " choice
if [[ ${choice} == "quit" ]] || [[ ${choice} == "${sessions_counter}" ]]; then
break
elif [[ -z ${choice} ]] || [[ -z ${sessions_map[${choice}]} ]]; then
clear
echo "Sélection invalide."
else
ttyplay /home/"${selected_option}"/"${sessions_map[${choice}]}"
fi
done
fi
done
}
function servers_access_control() {
@ -147,6 +155,11 @@ function admin_rights_control() {
secure_file_editor "/opt/public/rights/admin_rights.txt"
}
function transfer_rights_control() {
echo -e "Editez les droits de transfert de fichiers ci dessous.\nFormat : nom_serveur user1,user2,...\nSi le fichier est vide, les transferts sont refuses pour tous."
secure_file_editor "/opt/public/rights/transfer_rights.txt"
}
function main_menu() {
clear
ADMIN_RIGHTS_PATH="opt/public/rights"
@ -163,39 +176,57 @@ function main_menu() {
}
}' "${ADMIN_RIGHTS_FILE}")
if [[ -z ${ADMIN_RIGHTS} ]]; then
echo -e "Vous n'avez aucune autorisation d'administration.\nVous pouvez cependant vous connecter aux serveurs dont l'accès vous est autorisé."
fi
echo "Veuillez sélectionner une option d'administration :"
counter=0
declare -A adminrights_map
adminrights_list=()
while read -r line; do
admin_right=$(echo "${line}" | cut -d ' ' -f 1)
admin_right_pretty_name=$(echo "${line}" | cut -d ' ' -f 2)
adminrights_map[${counter}]="${admin_right} ${admin_right_pretty_name}"
echo "${counter}) ${admin_right_pretty_name}"
counter=$((counter + 1))
if [[ -n ${admin_right_pretty_name} ]]; then
adminrights_list[${counter}]="${admin_right} ${admin_right_pretty_name}"
counter=$((counter + 1))
fi
done <<<"${ADMIN_RIGHTS}"
if [[ ${counter} -gt 0 ]]; then
echo "Veuillez sélectionner une option d'administration :"
for ((idx=0; idx<counter; idx++)); do
echo "${idx}) $(echo "${adminrights_list[${idx}]}" | cut -d ' ' -f 2-)"
done
else
echo "Vous n'avez aucune autorisation d'administration."
fi
echo "Vous pouvez cependant vous connecter aux serveurs dont l'accès vous est autorisé."
local servers_access_idx=${counter}
echo "${counter}) Tapez 'servers_access' ou ${counter} pour vous connecter a un serveur."
counter=$((counter + 1))
local logs_idx=${counter}
echo "${counter}) Tapez 'logs' ou ${counter} pour consulter les logs de transfert."
counter=$((counter + 1))
local quit_idx=${counter}
echo "${counter}) Tapez 'quit' ou ${counter} pour vous déconnecter."
read -r -p "Votre choix (0-${counter}): " choice
if [[ ${choice} == "servers_access" ]] || [[ ${choice} == "$((counter - 1))" ]]; then
if [[ ${choice} == "servers_access" ]] || [[ ${choice} == "${servers_access_idx}" ]]; then
bash /opt/public/scripts/server_menu.sh
elif [[ ${choice} == "quit" ]] || [[ ${choice} == "${counter}" ]]; then
elif [[ ${choice} == "logs" ]] || [[ ${choice} == "${logs_idx}" ]]; then
clear
if [[ -f /var/log/monosphere/transfers.log ]]; then
cat /var/log/monosphere/transfers.log
else
echo "Aucun log de transfert disponible."
fi
read -r -p "Appuyez sur Entree pour continuer..."
elif [[ ${choice} == "quit" ]] || [[ ${choice} == "${quit_idx}" ]]; then
echo "Déconnexion du bastion."
exit 0
elif [[ -z ${choice} ]] || [[ -z ${adminrights_map[${choice}]} ]]; then
elif [[ -z ${choice} ]] || [[ -z ${adminrights_list[${choice}]+isset} ]]; then
clear
echo "Sélection invalide."
else
local selected_option
selected_option="${adminrights_map[${choice}]}"
selected_option="${adminrights_list[${choice}]}"
case "$(echo "${selected_option}" | cut -d ' ' -f 1)" in
"sessionswatch_admins")
@ -217,6 +248,11 @@ function main_menu() {
admin_rights_control
;;
"transfercontrol_admins")
clear
transfer_rights_control
;;
#
# "cluster_admins")
#

View File

@ -1,3 +1,4 @@
sessionswatch_admins Visionnage_des_sessions_du_bastion bastion
serverscontrol_admins Administration_des_acces_serveurs bastion
adminscontrol_admins Administration_des_privileges bastion
transfercontrol_admins Gestion_des_droits_de_transfert bastion

View File

@ -104,7 +104,14 @@ good_msg "Création des utilisateurs terminée."
info_msg "Monosphere configure le répertoire public."
chown -R root:bastionadmin /opt/public
chmod -R 775 /opt/public
good_msg "Répertoire public configuré."
info_msg "Configuration des répertoires de logs et droits."
touch /opt/public/rights/transfer_rights.txt
mkdir -p /var/log/monosphere
chmod 777 /var/log/monosphere
touch /var/log/monosphere/transfers.log
chmod 666 /var/log/monosphere/transfers.log
good_msg "Répertoires configurés."
info_msg "Démarrage du service SSHD de Monosphere."
rc-status

View File

@ -19,9 +19,144 @@ if [[ -z ${USER_SERVERS} ]]; then
exit 1
fi
TRANSFER_LOG="/var/log/monosphere/transfers.log"
TRANSFER_RIGHTS_FILE="/opt/public/rights/transfer_rights.txt"
mkdir -p "$(dirname "${TRANSFER_LOG}")" 2>/dev/null
touch "${TRANSFER_LOG}" 2>/dev/null
chmod 666 "${TRANSFER_LOG}" 2>/dev/null
check_transfer_rights() {
local server_name="$1"
if [[ ! -f ${TRANSFER_RIGHTS_FILE} ]] || [[ ! -s ${TRANSFER_RIGHTS_FILE} ]]; then
return 0
fi
local user_allowed
user_allowed=$(awk -v server="${server_name}" -v user="${CONNECTED_USER}" '
$1 == server {
split($2, ulist, ",");
for (i in ulist) {
if (ulist[i] == user || ulist[i] == "*") { print "yes"; exit; }
}
}
' "${TRANSFER_RIGHTS_FILE}")
if [[ -z ${user_allowed} ]]; then
return 1
fi
return 0
}
scp_to_target() {
local src="$1" ip="$2" port="$3" user="$4" dest="$5" authmethod="$6" authfile="$7"
if [[ -z ${authmethod} ]]; then
scp -o StrictHostKeyChecking=accept-new -P "${port}" "${src}" "${user}@${ip}:${dest}" 2>&1
elif [[ ${authmethod} == "key" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${authfile} ]]; then
scp -o StrictHostKeyChecking=accept-new -i "/${AUTHORIZED_SERVERS_PATH}/${authfile}" -P "${port}" "${src}" "${user}@${ip}:${dest}" 2>&1
elif [[ ${authmethod} == "password" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${authfile} ]]; then
sshpass -p "$(cat /${AUTHORIZED_SERVERS_PATH}/${authfile})" scp -o StrictHostKeyChecking=accept-new -P "${port}" "${src}" "${user}@${ip}:${dest}" 2>&1
else
return 1
fi
}
ssh_to_target_cat() {
local ip="$1" port="$2" user="$3" path="$4" authmethod="$5" authfile="$6"
if [[ -z ${authmethod} ]]; then
ssh -T -o StrictHostKeyChecking=accept-new -p "${port}" "${user}@${ip}" "cat '${path}'" < /dev/null
elif [[ ${authmethod} == "key" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${authfile} ]]; then
ssh -T -o StrictHostKeyChecking=accept-new -i "/${AUTHORIZED_SERVERS_PATH}/${authfile}" -p "${port}" "${user}@${ip}" "cat '${path}'" < /dev/null
elif [[ ${authmethod} == "password" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${authfile} ]]; then
sshpass -p "$(cat /${AUTHORIZED_SERVERS_PATH}/${authfile})" ssh -T -o StrictHostKeyChecking=accept-new -p "${port}" "${user}@${ip}" "cat '${path}'" < /dev/null
else
return 1
fi
}
log_transfer() {
local action="$1" server="$2" path="$3" size="$4" status="$5"
echo "$(date '+%Y-%m-%d %H:%M:%S') USER=${CONNECTED_USER} ACTION=${action} SERVER=${server} FILE=${path} SIZE=${size} STATUS=${status}" >> "${TRANSFER_LOG}"
}
if [[ -n ${SSH_ORIGINAL_COMMAND} ]]; then
case "${SSH_ORIGINAL_COMMAND}" in
"push_file "*)
args="${SSH_ORIGINAL_COMMAND#push_file }"
server_name=$(echo "${args}" | cut -d ' ' -f 1)
dest_path=$(echo "${args}" | cut -d ' ' -f 2-)
if [[ -z ${server_name} ]] || [[ -z ${dest_path} ]]; then
echo "Usage: push_file <server_name> <remote_dest_path>"
exit 1
fi
server_line=$(echo "${USER_SERVERS}" | awk -v name="${server_name}" '$3 == name {print; exit}')
if [[ -z ${server_line} ]]; then
echo "Serveur \"${server_name}\" non trouve ou non autorise."
exit 1
fi
if ! check_transfer_rights "${server_name}"; then
echo "Vous n'avez pas le droit de transferer des fichiers vers ${server_name}."
exit 1
fi
srv_ip=$(echo "${server_line}" | cut -d ' ' -f 1)
srv_port=$(echo "${server_line}" | cut -d ' ' -f 2)
srv_user=$(echo "${server_line}" | cut -d ' ' -f 4)
srv_authmethod=$(echo "${server_line}" | cut -d ' ' -f 6)
srv_authfile=$(echo "${server_line}" | cut -d ' ' -f 7)
tmpfile=$(mktemp /tmp/.push_XXXXXX)
cat > "${tmpfile}"
file_size=$(stat -c %s "${tmpfile}" 2>/dev/null || stat -f %z "${tmpfile}" 2>/dev/null)
scp_to_target "${tmpfile}" "${srv_ip}" "${srv_port}" "${srv_user}" "${dest_path}" "${srv_authmethod}" "${srv_authfile}"
exit_code=$?
rm -f "${tmpfile}"
if [[ ${exit_code} -eq 0 ]]; then
log_transfer "push" "${server_name}" "${dest_path}" "${file_size:-0}" "success"
else
log_transfer "push" "${server_name}" "${dest_path}" "${file_size:-0}" "failed"
fi
exit ${exit_code}
;;
"retrieve_file "*)
args="${SSH_ORIGINAL_COMMAND#retrieve_file }"
server_name=$(echo "${args}" | cut -d ' ' -f 1)
remote_path=$(echo "${args}" | cut -d ' ' -f 2-)
if [[ -z ${server_name} ]] || [[ -z ${remote_path} ]]; then
echo "Usage: retrieve_file <server_name> <remote_path>"
exit 1
fi
server_line=$(echo "${USER_SERVERS}" | awk -v name="${server_name}" '$3 == name {print; exit}')
if [[ -z ${server_line} ]]; then
echo "Serveur \"${server_name}\" non trouve ou non autorise."
exit 1
fi
if ! check_transfer_rights "${server_name}"; then
echo "Vous n'avez pas le droit de transferer des fichiers vers ${server_name}."
exit 1
fi
srv_ip=$(echo "${server_line}" | cut -d ' ' -f 1)
srv_port=$(echo "${server_line}" | cut -d ' ' -f 2)
srv_user=$(echo "${server_line}" | cut -d ' ' -f 4)
srv_authmethod=$(echo "${server_line}" | cut -d ' ' -f 6)
srv_authfile=$(echo "${server_line}" | cut -d ' ' -f 7)
ssh_to_target_cat "${srv_ip}" "${srv_port}" "${srv_user}" "${remote_path}" "${srv_authmethod}" "${srv_authfile}"
exit_code=$?
if [[ ${exit_code} -eq 0 ]]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') USER=${CONNECTED_USER} ACTION=retrieve SERVER=${server_name} FILE=${remote_path} STATUS=success" >> "${TRANSFER_LOG}"
else
echo "$(date '+%Y-%m-%d %H:%M:%S') USER=${CONNECTED_USER} ACTION=retrieve SERVER=${server_name} FILE=${remote_path} STATUS=failed" >> "${TRANSFER_LOG}"
fi
exit ${exit_code}
;;
*)
echo "Commande non reconnue: ${SSH_ORIGINAL_COMMAND}"
echo "Commandes supportees:"
echo " push_file <server> <dest_path> - Pousser stdin vers un serveur distant"
echo " retrieve_file <server> <src_path> - Recuperer un fichier distant vers stdout"
exit 1
;;
esac
fi
function main_menu() {
if [[ -z $choice ]] || [[ ${choice} == "null" ]]; then
clear
echo "Veuillez sélectionner un serveur auquel vous connecter :"
fi
@ -92,4 +227,5 @@ function main_menu() {
while true; do
main_menu
clear
done

4
transfer_rights.txt Normal file
View File

@ -0,0 +1,4 @@
# Format: server_custom_name user1,user2,...
# Les utilisateurs listés peuvent transferer des fichiers vers ces serveurs.
# Si le fichier n'existe pas, tous les utilisateurs autorises (via authorized_servers.txt) peuvent transferer.
# example-fake-server bastion