diff --git a/Dockerfile b/Dockerfile index 7457427..3530d49 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM alpine:3.20.0 AS monosphere-builder #Setting default settings, please change them at run -ARG MONOSPHERE_VERSION="1.0.4 Alpha" +ARG MONOSPHERE_VERSION="2.0.5 Alpha" #Defining build settings @@ -13,7 +13,7 @@ USER root #Updating and installing required dependencies -RUN apk add make=4.4.1-r2 git=2.45.2-r0 gcc=13.2.1_git20240309-r0 alpine-sdk=1.0-r1 && \ +RUN apk add make=4.4.1-r2 git=2.45.3-r0 gcc=13.2.1_git20240309-r0 alpine-sdk=1.0-r1 && \ addgroup root abuild && \ mkdir -p /var/cache/distfiles && \ chmod a+w /var/cache/distfiles @@ -51,7 +51,7 @@ USER root #Preparations #Updating and installing required dependencies -RUN apk add openssh-server=9.7_p1-r4 openssh-client=9.7_p1-r4 sudo=1.9.15_p5-r0 openrc=0.54-r1 bash=5.2.26-r0 sshpass=1.10-r0 gawk=5.3.0-r1 && \ +RUN apk add openssh-server=9.7_p1-r4 openssh-client=9.7_p1-r4 sudo=1.9.15_p5-r0 openrc=0.54-r1 bash=5.2.26-r0 sshpass=1.10-r0 gawk=5.3.0-r1 nano=8.0-r0 && \ apk --no-cache add shadow=4.15.1-r0 @@ -60,12 +60,13 @@ RUN rc-update add sshd && \ mkdir -p /run/openrc && \ touch /run/openrc/softlevel - #Copying from build and adding default configuration files COPY --from=monosphere-builder /root/scripts/monosphere_banner.txt /root/scripts/monosphere_banner.txt ADD entrypoint.sh /root/scripts/ 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 bastion_users.txt /root/scripts/users/ ADD sshd_config /etc/ssh/ diff --git a/admin_menu.sh b/admin_menu.sh new file mode 100644 index 0000000..79aa2ea --- /dev/null +++ b/admin_menu.sh @@ -0,0 +1,170 @@ +#!/bin/bash + +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=1 + 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 (1-${users_counter}): " choice + + if [[ ${choice} == "quit" ]] || [[ ${choice} == "${users_counter}" ]]; then + main_menu + elif [[ -z ${choice} ]] || [[ -z ${users_map[${choice}]} ]]; then + echo "Sélection invalide." + else + while true; do + local selected_option + selected_option="${users_map[${choice}]}" + 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 ${users_map[${choice}]} ]]; then + 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 + +} + +function servers_access_control() { + echo -e "Choisissez une option d'administration des serveurs ci dessous :" + echo -e "1) Ajout de fichiers clés privées/mots de passes pour l'authentification aux serveurs distants.\n2) Modification des droits d'accès aux serveurs.\n3) Tapez 'quit' ou 3 pour revenir au menu précédent." + + read -r -p "Votre choix (1-3): " choice + + case "${choice}" in + "1") + echo -e "Option non implémentée pour le moment.\nElle sera ajoutée lors d'une prochaine mise à jour." + ;; + + "2") + echo -e "Veuillez bien vérifier la syntaxe de votre configuration avant de valider cette dernière.\nPour plus d'informations, consultez la documentation de Monosphere." + nano /opt/public/servers/authorized_servers.txt + ;; + + "3" | "quit") + main_menu + ;; + + *) + echo "Sélection invalide." + ;; + esac + + while true; do + servers_access_control + done +} + +function main_menu() { + ADMIN_RIGHTS_PATH="opt/public/rights" + ADMIN_RIGHTS_FILE="/${ADMIN_RIGHTS_PATH}/admin_rights.txt" + CONNECTED_ADMIN="$(whoami)" + + ADMIN_RIGHTS=$(awk -v user="${CONNECTED_ADMIN}" ' +{ + split($3, users, ","); + for (i in users) { + if (users[i] == user) { + print $0; + } + } +}' "${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=1 + declare -A adminrights_map + 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)) + done <<<"${ADMIN_RIGHTS}" + + echo "${counter}) Tapez 'servers_access' ou ${counter} pour vous connecter a un serveur." + counter=$((counter + 1)) + echo "${counter}) Tapez 'quit' ou ${counter} pour vous déconnecter." + + read -r -p "Votre choix (1-${counter}): " choice + + if [[ ${choice} == "servers_access" ]] || [[ ${choice} == "$((counter - 1))" ]]; then + bash /opt/public/scripts/server_menu.sh + elif [[ ${choice} == "quit" ]] || [[ ${choice} == "${counter}" ]]; then + echo "Déconnexion du bastion." + exit 0 + elif [[ -z ${choice} ]] || [[ -z ${adminrights_map[${choice}]} ]]; then + echo "Sélection invalide." + else + local selected_option + selected_option="${adminrights_map[${choice}]}" + case "$(echo "${selected_option}" | cut -d ' ' -f 1)" in + + "sessionswatch_admins") + sessions_viewer + ;; + + "serverscontrol_admins") + servers_access_control + ;; + # + # "usercontrol_admins") + # + # ;; + # + # "adminscontrol_admins") + # + # ;; + # + # "cluster_admins") + # + # ;; + + *) + echo -e "Un problème de configuration a été détecté sur \nles options du droit administrateur sélectionné.\nVeuillez contacter votre administrateur." + ;; + esac + fi + + while true; do + main_menu + done +} + +main_menu diff --git a/admin_rights.txt b/admin_rights.txt new file mode 100644 index 0000000..693afd1 --- /dev/null +++ b/admin_rights.txt @@ -0,0 +1,2 @@ +sessionswatch_admins Visionnage_des_sessions_du_bastion bastion +serverscontrol_admins Administration_des_acces_serveurs bastion diff --git a/authorized_servers.txt b/authorized_servers.txt index e69de29..952fc90 100644 --- a/authorized_servers.txt +++ b/authorized_servers.txt @@ -0,0 +1 @@ +255.255.255.256 22 example-fake-server example-fake-user bastion diff --git a/entrypoint.sh b/entrypoint.sh index c753e36..d989de5 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,21 +2,24 @@ if ! grep -qo "^Port ${PORT}$" /etc/ssh/sshd_config; then echo "Génération de la configuration de SSH pour le bastion Monosphere..." + echo "Port selectionne pour la connexion SSH : ${PORT}" echo "Port ${PORT}" >>/etc/ssh/sshd_config echo "#Last authentication configurations" >>/etc/ssh/sshd_config if [[ ${PASSWORD_AUTH} -eq "1" ]]; then + echo "Authentification par mot de passe autorisee." echo "PasswordAuthentication yes" >>/etc/ssh/sshd_config else + echo "Authentification par mot de passe interdite." echo "PasswordAuthentication no" >>/etc/ssh/sshd_config fi if [[ ${KEY_AUTH} -eq "1" ]]; then + echo "Authentification par clés privées autorisee." echo "PubkeyAuthentication yes" >>/etc/ssh/sshd_config else + echo "Authentification par clés privées interdite." echo "PubkeyAuthentication no" >>/etc/ssh/sshd_config fi fi -sshd -t -echo "Configuration du service SSHD de Monosphere vérifiée." echo "Monosphere active et execute les scripts personalisés" chown -R root:root /opt/custom @@ -43,6 +46,10 @@ echo "Fin de la création des groupes d'utilisateurs." echo "Création des utilisateurs en cours..." userfile=$(cat /root/scripts/users/bastion_users.txt) +if [[ -z ${userfile} ]]; then + echo "Configuration utilisateur introuvable, veuillez vérifier votre configuration." + exit 1 +fi for userinfo in ${userfile}; do user=$(echo "${userinfo}" | cut -d ';' -f 1) is_bastion=$(echo "${userinfo}" | cut -d ';' -f 2) @@ -58,6 +65,7 @@ for userinfo in ${userfile}; do if ! grep -qo "^${user} ALL=(ALL) NOPASSWD:" /etc/sudoers; then echo "${user} ALL=(ALL) NOPASSWD: /usr/local/bin/ttyplay*" | sudo EDITOR='tee -a' visudo echo "${user} ALL=(ALL) NOPASSWD: /bin/ls*" | sudo EDITOR='tee -a' visudo + echo "${user} ALL=(ALL) NOPASSWD: nano /opt/public/servers/authorized_servers.txt" fi mkdir /home/"${user}" ln -s /opt/public/scripts/server_menu.sh /home/"${user}"/server_menu.sh @@ -78,13 +86,18 @@ for userinfo in ${userfile}; do fi done echo "Création des utilisateurs terminée." -echo "Monosphere a bien été configuré et démarré avec succès." echo "Démarrage du service SSHD de Monosphere." rc-status rc-service sshd restart -echo "Le bastion Monosphere est désormais en marche." +if sshd -t; then + echo "Configuration du service SSHD de Monosphere vérifiée et valide." + echo "Monosphere a bien été configuré et démarré avec succès." +else + echo -e "Configuration du service SSHD de Monosphere invalide\n Veuillez vérifier la configuration et relancer le deploiement." + exit 1 +fi # Keep the container running tail -f /dev/null diff --git a/server_menu.sh b/server_menu.sh index 95fab8d..76d9627 100644 --- a/server_menu.sh +++ b/server_menu.sh @@ -14,7 +14,7 @@ USER_SERVERS=$(awk -v user="${CONNECTED_USER}" ' } }' "${AUTHORIZED_SERVERS_FILE}") -if [[ -z "${USER_SERVERS}" ]]; then +if [[ -z ${USER_SERVERS} ]]; then echo "Vous n'avez pas l'autorisation de vous connecter à un serveur." exit 1 fi @@ -40,10 +40,10 @@ function main_menu() { read -r -p "Votre choix (1-${counter}): " choice - if [[ "${choice}" == "quit" ]] || [[ "${choice}" == "${counter}" ]]; then + if [[ ${choice} == "quit" ]] || [[ ${choice} == "${counter}" ]]; then echo "Déconnexion du bastion." exit 0 - elif [[ -z "${choice}" ]] || [[ -z "${server_map[${choice}]}" ]]; then + elif [[ -z ${choice} ]] || [[ -z ${server_map[${choice}]} ]]; then echo "Sélection invalide." else local selected_server diff --git a/sshd_config b/sshd_config index fd8f3e8..0ce3926 100644 --- a/sshd_config +++ b/sshd_config @@ -166,7 +166,12 @@ AllowStreamLocalForwarding no Match Group bastionuser ForceCommand /opt/public/scripts/server_menu.sh X11Forwarding no +Match Group bastionadmin + ForceCommand /opt/public/scripts/admin_menu.sh + X11Forwarding no # End the 'Match' block Match all + ForceCommand echo -e "===========================================================\nSorry, you re not part of the bastion s users or administrators and have therefore no access.\nPlease contact your administrator for further informations.\n==========================================================="; exit + X11Forwarding no #Used port number