Candidate 3.5.0
This commit is contained in:
parent
c03d254f90
commit
75737165eb
@ -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 && \
|
||||
|
||||
85
README.md
85
README.md
@ -43,6 +43,9 @@ Voici une liste des différentes fonctionnalités déjà en place sur le bastion
|
||||
- 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).
|
||||
- Transfert de fichiers vers les serveurs distants, accessible depuis le menu du bastion ou via des commandes SSH non-interactives (`stage_file`/`retrieve_file`).
|
||||
- Contrôle des droits de transfert par serveur, gérable par les administrateurs.
|
||||
- Journalisation complète des 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 une option pour le transfert de fichiers au travers du bastion vers les machines distantes.
|
||||
- [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.
|
||||
|
||||
@ -124,9 +130,10 @@ docker run -d -p 22:22 \
|
||||
-e KEY_AUTH=1 \
|
||||
-e HOSTNAME=monosphere-bastion \
|
||||
-v /datasets/monosphere-bastion/servers:/opt/public/servers \
|
||||
-v /datasets/monosphere-bastion/transfer:/opt/public/transfer \
|
||||
-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 \
|
||||
-p "22:22" \
|
||||
--name monosphere-bastion siphonight/monosphere-bastion:latest
|
||||
```
|
||||
@ -147,9 +154,10 @@ services:
|
||||
- HOSTNAME=monosphere-bastion
|
||||
volumes:
|
||||
- /datasets/monosphere-bastion/servers:/opt/public/servers
|
||||
- /datasets/monosphere-bastion/transfer:/opt/public/transfer
|
||||
- /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
|
||||
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.* |
|
||||
| **/opt/public/transfer** | Aucun fichier attendu (répertoire de staging vide). | *Répertoire partagé utilisé pour déposer les fichiers à transferer vers les serveurs distants. Il est accessible en écriture par tous les utilisateurs du bastion.* |
|
||||
|
||||
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,40 @@ 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
|
||||
|
||||
Depuis la version 3.5.0, le bastion Monosphere supporte le transfert de fichiers vers les serveurs distants.
|
||||
|
||||
Deux méthodes sont disponibles :
|
||||
|
||||
#### Transfert depuis le menu interactif
|
||||
|
||||
1. Connectez-vous au bastion et sélectionnez l'option **`t`** dans le menu des serveurs.
|
||||
2. Choisissez le serveur de destination parmi ceux auxquels vous avez accès.
|
||||
3. Sélectionnez **Upload** (bastion → serveur) ou **Download** (serveur → bastion).
|
||||
4. Pour un upload, précisez le chemin du fichier source sur le bastion (dans `/opt/public/transfer/`) et le chemin de destination sur le serveur distant.
|
||||
5. Pour un download, précisez le chemin source sur le serveur distant et le nom de destination dans `/opt/public/transfer/`.
|
||||
|
||||
Les fichiers à uploader doivent d'abord être déposés dans le répertoire de staging `/opt/public/transfer/`. Ce répertoire est accessible en écriture par tous les utilisateurs du bastion. Vous pouvez y déposer des fichiers via un volume Docker monté sur ce répertoire.
|
||||
|
||||
#### Transfert non-interactif (SSH_ORIGINAL_COMMAND)
|
||||
|
||||
Le bastion supporte deux commandes non-interactives pour le transfert de fichiers, utilisables directement depuis votre machine locale :
|
||||
|
||||
**Déposer un fichier sur le bastion (stage) :**
|
||||
```bash
|
||||
cat monfichier.txt | ssh user@bastion 'stage_file monfichier.txt'
|
||||
```
|
||||
|
||||
**Récupérer un fichier depuis un serveur distant :**
|
||||
```bash
|
||||
ssh user@bastion 'retrieve_file nom_serveur /chemin/vers/fichier.txt' > monfichier.txt
|
||||
```
|
||||
|
||||
Ces commandes respectent les droits d'accès : vous ne pouvez transférer que vers les serveurs auxquels vous avez accès et pour lesquels vous possédez les droits de transfert.
|
||||
|
||||
Tous les transferts sont journalisés dans `/var/log/monosphere/transfers.log`.
|
||||
|
||||
### 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 +455,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 +619,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.
|
||||
|
||||
167
admin_menu.sh
167
admin_menu.sh
@ -37,62 +37,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 +150,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 +171,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 +243,11 @@ function main_menu() {
|
||||
admin_rights_control
|
||||
;;
|
||||
|
||||
"transfercontrol_admins")
|
||||
clear
|
||||
transfer_rights_control
|
||||
;;
|
||||
|
||||
#
|
||||
# "cluster_admins")
|
||||
#
|
||||
|
||||
@ -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
|
||||
|
||||
@ -104,7 +104,16 @@ 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 du répertoire de transfert de fichiers."
|
||||
mkdir -p /opt/public/transfer
|
||||
chmod 777 /opt/public/transfer
|
||||
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épertoire de transfert et de logs configurés."
|
||||
|
||||
info_msg "Démarrage du service SSHD de Monosphere."
|
||||
rc-status
|
||||
|
||||
251
server_menu.sh
251
server_menu.sh
@ -19,9 +19,252 @@ if [[ -z ${USER_SERVERS} ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TRANSFER_DIR="/opt/public/transfer"
|
||||
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
|
||||
|
||||
if [[ -n ${SSH_ORIGINAL_COMMAND} ]]; then
|
||||
case "${SSH_ORIGINAL_COMMAND}" in
|
||||
"stage_file "*)
|
||||
filename="${SSH_ORIGINAL_COMMAND#stage_file }"
|
||||
if [[ -z ${filename} ]] || [[ ${filename} =~ [/] ]] || [[ ${filename} == ".." ]] || [[ ${filename} == "." ]]; then
|
||||
echo "Usage: stage_file <filename> (chemin simple, sans /)"
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "${TRANSFER_DIR}"
|
||||
cat > "${TRANSFER_DIR}/${filename}"
|
||||
size=$(stat -c %s "${TRANSFER_DIR}/${filename}" 2>/dev/null || stat -f %z "${TRANSFER_DIR}/${filename}" 2>/dev/null)
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') USER=${CONNECTED_USER} ACTION=stage FILE=${filename} SIZE=${size:-0} STATUS=success" >> "${TRANSFER_LOG}"
|
||||
exit 0
|
||||
;;
|
||||
"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
|
||||
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)
|
||||
if [[ -z ${srv_authmethod} ]]; then
|
||||
ssh -T -o StrictHostKeyChecking=accept-new -p "${srv_port}" "${srv_user}@${srv_ip}" "cat '${remote_path}'" < /dev/null
|
||||
elif [[ ${srv_authmethod} == "key" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${srv_authfile} ]]; then
|
||||
ssh -T -o StrictHostKeyChecking=accept-new -i "/${AUTHORIZED_SERVERS_PATH}/${srv_authfile}" -p "${srv_port}" "${srv_user}@${srv_ip}" "cat '${remote_path}'" < /dev/null
|
||||
elif [[ ${srv_authmethod} == "password" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${srv_authfile} ]]; then
|
||||
sshpass -p "$(cat /${AUTHORIZED_SERVERS_PATH}/${srv_authfile})" ssh -T -o StrictHostKeyChecking=accept-new -p "${srv_port}" "${srv_user}@${srv_ip}" "cat '${remote_path}'" < /dev/null
|
||||
else
|
||||
echo "Erreur d'authentification pour le serveur ${server_name}."
|
||||
exit 1
|
||||
fi
|
||||
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: stage_file <filename>, retrieve_file <server_name> <remote_path>"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
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}"
|
||||
}
|
||||
|
||||
file_transfer_menu() {
|
||||
local choice action srv_line srv_name srv_ip srv_port srv_user selected_server
|
||||
|
||||
mkdir -p "${TRANSFER_DIR}"
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " Transfert de fichiers"
|
||||
echo "=============================================="
|
||||
echo "Repertoire de staging (deposez vos fichiers) :"
|
||||
echo " ${TRANSFER_DIR}"
|
||||
echo ""
|
||||
|
||||
echo "Serveurs disponibles :"
|
||||
local counter=0
|
||||
declare -A srv_map
|
||||
while read -r line; do
|
||||
srv_ip=$(echo "${line}" | cut -d ' ' -f 1)
|
||||
srv_port=$(echo "${line}" | cut -d ' ' -f 2)
|
||||
srv_name=$(echo "${line}" | cut -d ' ' -f 3)
|
||||
srv_user=$(echo "${line}" | cut -d ' ' -f 4)
|
||||
srv_authmethod=$(echo "${line}" | cut -d ' ' -f 6)
|
||||
srv_authfile=$(echo "${line}" | cut -d ' ' -f 7)
|
||||
srv_map[${counter}]="${srv_ip} ${srv_port} ${srv_user} ${srv_authmethod} ${srv_authfile} ${srv_name}"
|
||||
echo " ${counter}) ${srv_name} - ${srv_user}@${srv_ip}:${srv_port}"
|
||||
counter=$((counter + 1))
|
||||
done <<< "${USER_SERVERS}"
|
||||
|
||||
echo ""
|
||||
read -r -p "Selectionnez un serveur (0-$((counter-1))) ou 'q' pour quitter : " choice
|
||||
if [[ ${choice} == "q" ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ -z ${srv_map[${choice}]} ]]; then
|
||||
echo "Selection invalide."
|
||||
read -r -p "Appuyez sur Entree pour continuer..."
|
||||
return
|
||||
fi
|
||||
|
||||
selected_server="${srv_map[${choice}]}"
|
||||
srv_ip=$(echo "${selected_server}" | cut -d ' ' -f 1)
|
||||
srv_port=$(echo "${selected_server}" | cut -d ' ' -f 2)
|
||||
srv_user=$(echo "${selected_server}" | cut -d ' ' -f 3)
|
||||
srv_authmethod=$(echo "${selected_server}" | cut -d ' ' -f 4)
|
||||
srv_authfile=$(echo "${selected_server}" | cut -d ' ' -f 5)
|
||||
srv_name=$(echo "${selected_server}" | cut -d ' ' -f 6)
|
||||
|
||||
if [[ -f ${TRANSFER_RIGHTS_FILE} ]] && [[ -s ${TRANSFER_RIGHTS_FILE} ]]; then
|
||||
user_allowed=$(awk -v server="${srv_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
|
||||
echo "Vous n'avez pas le droit de transferer des fichiers vers ${srv_name}."
|
||||
read -r -p "Appuyez sur Entree pour continuer..."
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "1) Upload (bastion -> ${srv_name})"
|
||||
echo "2) Download (${srv_name} -> bastion)"
|
||||
read -r -p "Choix : " action
|
||||
|
||||
case "${action}" in
|
||||
"1")
|
||||
clear
|
||||
echo "===== Upload vers ${srv_name} ====="
|
||||
echo ""
|
||||
echo "Fichiers dans ${TRANSFER_DIR} :"
|
||||
ls -la "${TRANSFER_DIR}" 2>/dev/null || echo " (repertoire vide)"
|
||||
echo ""
|
||||
read -r -p "Chemin source (sur le bastion) : " source_path
|
||||
if [[ ! -f ${source_path} ]]; then
|
||||
echo "Erreur : le fichier source n'existe pas."
|
||||
read -r -p "Appuyez sur Entree pour continuer..."
|
||||
return
|
||||
fi
|
||||
read -r -p "Chemin de destination (sur ${srv_name}) : " dest_path
|
||||
if [[ -z ${dest_path} ]]; then
|
||||
echo "Erreur : chemin de destination vide."
|
||||
read -r -p "Appuyez sur Entree pour continuer..."
|
||||
return
|
||||
fi
|
||||
|
||||
local file_size file_name
|
||||
file_size=$(stat -c %s "${source_path}" 2>/dev/null || stat -f %z "${source_path}" 2>/dev/null)
|
||||
file_name=$(basename "${source_path}")
|
||||
|
||||
echo ""
|
||||
echo "Transfert en cours..."
|
||||
if [[ -z ${srv_authmethod} ]]; then
|
||||
scp -o StrictHostKeyChecking=accept-new -P "${srv_port}" "${source_path}" "${srv_user}@${srv_ip}:${dest_path}" 2>&1
|
||||
elif [[ ${srv_authmethod} == "key" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${srv_authfile} ]]; then
|
||||
scp -o StrictHostKeyChecking=accept-new -i "/${AUTHORIZED_SERVERS_PATH}/${srv_authfile}" -P "${srv_port}" "${source_path}" "${srv_user}@${srv_ip}:${dest_path}" 2>&1
|
||||
elif [[ ${srv_authmethod} == "password" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${srv_authfile} ]]; then
|
||||
sshpass -p "$(cat /${AUTHORIZED_SERVERS_PATH}/${srv_authfile})" scp -o StrictHostKeyChecking=accept-new -P "${srv_port}" "${source_path}" "${srv_user}@${srv_ip}:${dest_path}" 2>&1
|
||||
else
|
||||
echo "Erreur d'authentification pour ${srv_name}."
|
||||
return
|
||||
fi
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo ""
|
||||
echo "Transfert reussi."
|
||||
log_transfer "upload" "${srv_name}" "${dest_path}/${file_name}" "${file_size:-0}" "success"
|
||||
else
|
||||
echo ""
|
||||
echo "Echec du transfert."
|
||||
log_transfer "upload" "${srv_name}" "${dest_path}/${file_name}" "${file_size:-0}" "failed"
|
||||
fi
|
||||
;;
|
||||
"2")
|
||||
clear
|
||||
echo "===== Download depuis ${srv_name} ====="
|
||||
echo ""
|
||||
|
||||
read -r -p "Chemin source (sur ${srv_name}) : " source_path
|
||||
if [[ -z ${source_path} ]]; then
|
||||
echo "Erreur : chemin source vide."
|
||||
read -r -p "Appuyez sur Entree pour continuer..."
|
||||
return
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Fichiers dans ${TRANSFER_DIR} :"
|
||||
ls -la "${TRANSFER_DIR}" 2>/dev/null || echo " (repertoire vide)"
|
||||
echo ""
|
||||
read -r -p "Nom de destination (dans ${TRANSFER_DIR}) : " dest_name
|
||||
if [[ -z ${dest_name} ]]; then
|
||||
dest_name=$(basename "${source_path}")
|
||||
fi
|
||||
dest_name=$(basename "${dest_name}")
|
||||
if [[ -z ${dest_name} ]]; then
|
||||
echo "Erreur : nom de destination invalide."
|
||||
return
|
||||
fi
|
||||
|
||||
local dest_path="${TRANSFER_DIR}/${dest_name}"
|
||||
echo ""
|
||||
echo "Transfert en cours..."
|
||||
if [[ -z ${srv_authmethod} ]]; then
|
||||
scp -o StrictHostKeyChecking=accept-new -P "${srv_port}" "${srv_user}@${srv_ip}:${source_path}" "${dest_path}" 2>&1
|
||||
elif [[ ${srv_authmethod} == "key" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${srv_authfile} ]]; then
|
||||
scp -o StrictHostKeyChecking=accept-new -i "/${AUTHORIZED_SERVERS_PATH}/${srv_authfile}" -P "${srv_port}" "${srv_user}@${srv_ip}:${source_path}" "${dest_path}" 2>&1
|
||||
elif [[ ${srv_authmethod} == "password" ]] && [[ -f /${AUTHORIZED_SERVERS_PATH}/${srv_authfile} ]]; then
|
||||
sshpass -p "$(cat /${AUTHORIZED_SERVERS_PATH}/${srv_authfile})" scp -o StrictHostKeyChecking=accept-new -P "${srv_port}" "${srv_user}@${srv_ip}:${source_path}" "${dest_path}" 2>&1
|
||||
else
|
||||
echo "Erreur d'authentification pour ${srv_name}."
|
||||
return
|
||||
fi
|
||||
if [[ $? -eq 0 ]]; then
|
||||
local file_size
|
||||
file_size=$(stat -c %s "${dest_path}" 2>/dev/null || stat -f %z "${dest_path}" 2>/dev/null)
|
||||
echo ""
|
||||
echo "Transfert reussi."
|
||||
log_transfer "download" "${srv_name}" "${source_path}" "${file_size:-0}" "success"
|
||||
else
|
||||
echo ""
|
||||
echo "Echec du transfert."
|
||||
log_transfer "download" "${srv_name}" "${source_path}" "0" "failed"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Action invalide."
|
||||
;;
|
||||
esac
|
||||
|
||||
read -r -p "Appuyez sur Entree pour continuer..."
|
||||
}
|
||||
|
||||
function main_menu() {
|
||||
if [[ -z $choice ]] || [[ ${choice} == "null" ]]; then
|
||||
clear
|
||||
echo "Veuillez sélectionner un serveur auquel vous connecter :"
|
||||
fi
|
||||
|
||||
@ -44,6 +287,7 @@ function main_menu() {
|
||||
if [[ -z $choice ]] || [[ ${choice} == "null" ]]; then
|
||||
echo "${counter}) Tapez 'quit' ou ${counter} pour vous déconnecter."
|
||||
echo "f) Tapez 'f'<nom de l'hote> pour filtrer les entrées."
|
||||
echo "t) Tapez 't' pour transferer des fichiers."
|
||||
|
||||
read -r -p "Votre choix (0-${counter}) : " choice
|
||||
fi
|
||||
@ -62,6 +306,10 @@ function main_menu() {
|
||||
find_counter=$((find_counter + 1))
|
||||
done
|
||||
read -r -p "Votre choix (0-${counter}) : " choice
|
||||
elif [[ ${choice} == "t" ]]; then
|
||||
clear
|
||||
file_transfer_menu
|
||||
choice="null"
|
||||
elif [[ -z ${choice} ]] || [[ -z ${server_map[${choice}]} ]]; then
|
||||
echo "Sélection invalide."
|
||||
choice="null"
|
||||
@ -92,4 +340,5 @@ function main_menu() {
|
||||
|
||||
while true; do
|
||||
main_menu
|
||||
clear
|
||||
done
|
||||
|
||||
4
transfer_rights.txt
Normal file
4
transfer_rights.txt
Normal 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
|
||||
Loading…
x
Reference in New Issue
Block a user