#!/bin/bash -e # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Should we run as interactive mode ? (-s non interactive mode) INTERACTIVE=1 PASSHPORTDO="su - passhport -c" POSTGRESDO="su - postgres -c" POSTGRESPASS=$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 22) # or force it RED='\033[0;31m' GREEN='\033[0;32m' LGREEN='\033[1;32m' BLUE='\033[0;34m' NC='\033[0m' # No Color purge() { if [ ${INTERACTIVE} -eq 1 ] then echo -e "${RED}Be warned that ALL your installation will be erased. You will LOST DATA. ALL appache conf and postgresql databases will be erased by apt... this function should be used by devs only${NC}" echo -e "${RED}Last chance! Type yes if you accept to lose data and configuration, or exit with 'CTRL+C' :${NC}" read ANSWER; else ANSWER='yes' fi while [ "${ANSWER}" != 'yes' ] do echo 'Please type excatly "yes" or exit by pressing "CTRL+C".' read ANSWER done echo -e "${BLUE}Purge database/apache and dependances… ${NC}" apt purge -f python3-pip python3-venv git openssl libpython3-dev postgresql apache2 libapache2-mod-wsgi-py3 libpq-dev echo echo -e "${BLUE}Remove directories${NC}" rm -rf /etc/passhport/ /var/log/passhport/ /home/passhport /etc/bash_completion.d/passhport-admin /usr/local/bin/passhport-admin /var:lib/passhport echo -e "${BLUE}Remove user${NC}" userdel passhport } install_packages() { # Install dependances echo -e "${BLUE}Installing dependances via APT… ${NC}" apt update if [ ${DOCKER_INSTALL} -ne 1 ] then apt install -y python3-pip python3-venv git openssl libpython3-dev postgresql apache2 libapache2-mod-wsgi-py3 libpq-dev else apt install -y python3-pip python3-venv git openssl libpython3-dev apache2 libapache2-mod-wsgi-py3 libpq-dev fi echo } create_passhport_user() { # Passhport user creation echo -e "${BLUE}Create passhport user...${NC}" /usr/sbin/useradd --home-dir /home/passhport --shell /bin/bash --create-home passhport #in case the user exists but the homedir didn't... (happens if the purge is launched from a passhport ssh session) [ ! -e "/home/passhport/" ] && mkdir -p /home/passhport && chown passhport:passhport /home/passhport echo } download_sources() { # Download passhport code echo -e "${BLUE}Cloning passhport git from github...${NC}" if [ ! -z "${GITBRANCH}" ] then ${PASSHPORTDO} "git clone --single-branch --branch ${GITBRANCH} https://github.com/LibrIT/passhport.git" else ${PASSHPORTDO} "git clone https://github.com/LibrIT/passhport.git" fi echo } initial_config() { # Configure initial system and create env echo -e "${BLUE}Create conf and log directories...${NC}" mkdir -p /var/log/passhport/ chown passhport:passhport /var/log/passhport/ mkdir -p /etc/passhport mkdir -p /var/lib/passhport/ chown passhport:passhport /var/lib/passhport cp /home/passhport/passhport/passhportd/passhportd.ini /etc/passhport/. cp /home/passhport/passhport/passhport/passhport.ini /etc/passhport/. cp /home/passhport/passhport/passhport-admin/passhport-admin.ini /etc/passhport/. cp /home/passhport/passhport/passhportd/passhportd.ini /etc/passhport/. sed -i -e 's#SQLALCHEMY_DATABASE_DIR\s*=.*#SQLALCHEMY_DATABASE_DIR = /var/lib/passhport/#' /etc/passhport/passhportd.ini sed -i -e 's#LISTENING_IP\s*=.*#LISTENING_IP = 0.0.0.0#' /etc/passhport/passhportd.ini sed -i -e 's#SQLALCHEMY_MIGRATE_REPO\s*=.*#SQLALCHEMY_MIGRATE_REPO = /var/lib/passhport/db_repository#' /etc/passhport/passhportd.ini sed -i -e "s#SQLALCHEMY_DATABASE_URI\s*=.*#SQLALCHEMY_DATABASE_URI = postgresql://passhport:${POSTGRESPASS}@localhost/passhport#" /etc/passhport/passhportd.ini sed -i -e "s#PASSHPORTD_HOSTNAME\s*=.*#PASSHPORTD_HOSTNAME = localhost#" /etc/passhport/passhport-admin.ini sed -i -e "s#PASSHPORTD_HOSTNAME\s*=.*#PASSHPORTD_HOSTNAME = localhost#" /etc/passhport/passhport.ini echo } create_python_venv() { # Prepare venv echo -e "${BLUE}Installing mandatory packages in a new python3 venv...${NC}" ${PASSHPORTDO} "python3 -m venv passhport-run-env" ${PASSHPORTDO} "/home/passhport/passhport-run-env/bin/pip install -r /home/passhport/passhport/requirements.txt" ${PASSHPORTDO} "/home/passhport/passhport-run-env/bin/pip install psycopg2 psycopg2-binary flask_login flask_wtf requests" echo } generate_ssh_keys() { # Generate keys to be put on targes echo -e "${BLUE}Generating PaSSHport Legacy RSA (avoid to use it), legacy ecdsa (avoid to use it) and the modern ed25519 keys you will have to put on target…${NC}" ${PASSHPORTDO} '/usr/bin/ssh-keygen -t rsa -b 4096 -N "" -f "/home/passhport/.ssh/id_legacy_rsa"' ${PASSHPORTDO} '/usr/bin/ssh-keygen -t ecdsa -b 521 -N "" -f "/home/passhport/.ssh/id_legacy_ecdsa"' ${PASSHPORTDO} '/usr/bin/ssh-keygen -t ed25519 -b 521 -N "" -f "/home/passhport/.ssh/id_ed25519"' echo } install_bash_completion() { # Bash completion and binaries paths echo -e "${BLUE}Add passhport-admin in the pash and activate completion…${NC}" if [ ! -d "/etc/bash_completion.d/" ] then mkdir -p "/etc/bash_completion.d/" fi cp /home/passhport/passhport/tools/confs/passhport-admin.bash_completion /etc/bash_completion.d/passhport-admin . /etc/bash_completion.d/passhport-admin ln -s /home/passhport/passhport/tools/bin/passhport-admin.sh /usr/local/bin/passhport-admin echo } generate_ssl_certs() { # SSL Certificates time! echo -e "${BLUE}Creating some http certificates for the passhportd service${NC}" ${PASSHPORTDO} "mkdir -p /home/passhport/certs" ${PASSHPORTDO} "chmod 700 /home/passhport/certs" ${PASSHPORTDO} "openssl genrsa -out "/home/passhport/certs/key.pem" 4096" sed -i -e "s#^\(DNS.*\s*=\s*\)TO_CHANGE#\1`hostname -f`#g" /home/passhport/passhport/tools/confs/openssl-for-passhportd.cnf openssl req -new -key "/home/passhport/certs/key.pem" \ -config "/home/passhport/passhport/tools/confs/openssl-for-passhportd.cnf" \ -out "/home/passhport/certs/cert.pem" \ -subj "/C=FR/ST=Ile De France/L=Ivry sur Seine/O=LibrIT/OU=DSI/CN=passhport.librit.fr" \ -x509 \ -days 365 \ -sha256 \ -extensions v3_req echo } configure_postgresql() { # Postgresql echo -e "${BLUE}Configure access to postgresql database and initialize it...${NC}" ${POSTGRESDO} "createuser -D -S -R passhport && createdb -O passhport 'passhport'" ${POSTGRESDO} "psql -U postgres -d passhport -c \"alter user passhport with password '${POSTGRESPASS}';\"" ${PASSHPORTDO} "/home/passhport/passhport-run-env/bin/python /home/passhport/passhport/passhportd/db_create.py" echo } configure_apache_for_passhportd() { echo -e "${BLUE}Create apache2 configuration for passhport and restart apache2...${NC}" echo "Listen 5000 ServerName passhport SSLEngine on SSLCertificateFile /home/passhport/certs/cert.pem SSLCertificatekeyFile /home/passhport/certs/key.pem WSGIDaemonProcess passhport user=passhport group=passhport threads=5 python-home=/home/passhport/passhport-run-env/ WSGIScriptAlias / /home/passhport/passhport/tools/bin/passhportd.wsgi WSGIProcessGroup passhport WSGIApplicationGroup %{GLOBAL} # passhportd don't provides authentication, please filter by IP Require ip 127.0.0.1/8 ::1/128 " > /etc/apache2/sites-available/passhport.conf a2dissite 000-default a2enmod wsgi ssl a2ensite passhport echo } configure_apache_for_passhweb() { ################################################## PASSHWEB ################################################## # Note that to perform a standalone passhweb installation you can work with this part... # but you'll have to install some pip dependancies before echo -e "${BLUE}Install PaSSHWeb interface...${NC}" sed -e 's/^DEBUG\s*=.*/DEBUG = false/g' '/home/passhport/passhport/passhweb/passhweb.ini' > '/etc/passhport/passhweb.ini' echo " servername passhweb SSLEngine on SSLCertificateFile /home/passhport/certs/cert.pem SSLCertificatekeyFile /home/passhport/certs/key.pem WSGIDaemonProcess passhweb user=passhport group=passhport threads=5 python-home=/home/passhport/passhport-run-env/ WSGIScriptAlias / /home/passhport/passhport/tools/bin/passhweb.wsgi WSGIProcessGroup passhweb WSGIApplicationGroup %{GLOBAL} Require all granted Order deny,allow Allow from all LogLevel warn CustomLog /var/log/apache2/passhweb-access.log combined ErrorLog /var/log/apache2/passhweb-error.log " > /etc/apache2/sites-available/passhweb.conf a2ensite passhweb if [ $DOCKER_INSTALL -ne 1 ] then systemctl restart apache2 fi # Sleep 2 seconds so apache has enough time to start sleep 2 echo } initial_configuration() { echo -e "${BLUE}Adding root@localhost target…${NC}" [ ! -d "/root/.ssh" ] && mkdir -p "/root/.ssh" && chmod 700 "/root/.ssh" cat "/home/passhport/.ssh/id_ed25519.pub" >> "/root/.ssh/authorized_keys" ${PASSHPORTDO} 'passhport-admin target create root@localhost 127.0.0.1 --comment="Localhost target added during the PaSSHport installation process."' if [ ${INTERACTIVE} -eq 1 ] then echo -e "${GREEN}Do you want to add your first user now ? Y/n${NC}" read DO_CREATE_USER else DO_CREATE_USER='n' fi while [ "${DO_CREATE_USER,,}" != "y" ] && [ ! -z "${DO_CREATE_USER}" ] && [ "${DO_CREATE_USER,,}" != "n" ] do echo -e "${GREEN}Do you want to add your first user now ? Y/n${NC}" read DO_CREATE_USER done if [ "${DO_CREATE_USER,,}" == "y" ] || [ -z "${DO_CREATE_USER}" ] then echo -e "${LGREEN}Remember : no space in the user name!${NC}" ${PASSHPORTDO} "passhport-admin user create" echo -e "${LGREEN}Do you want to link this user to the target root@localhost ? Y/n${NC}" read DO_LINK_USER while [ "${DO_LINK_USER,,}" != "y" ] && [ ! -z "${DO_LINK_USER}" ] && [ "${DO_LINK_USER,,}" != "n" ] do echo -e "${LGREEN}Do you want to link this user to the target root@localhost ? Y/n${NC}" read DO_LINK_USER done if [ "${DO_LINK_USER,,}" == "y" ] || [ -z "${DO_LINK_USER}" ] then FIRST_USER=`${PASSHPORTDO} "passhport-admin user list"` ${PASSHPORTDO} "passhport-admin target adduser ${FIRST_USER} root@localhost" fi fi echo echo -e "${BLUE}PaSSHport should be installed on your system.${NC}" echo 'We test it with this command: curl -s --insecure https://localhost:5000' echo -ne "${GREEN}" curl -s --insecure https://localhost:5000 if [ ${INTERACTIVE} -eq 1 ] then echo -e "${BLUE}If you created your first user, you can connect to PaSSHport${NC}" echo -e "${BLUE}using 'ssh -i the_key_you_used passhport@PASSHPORT_HOST'${NC}" fi echo 'Installation is now done.' } install() { echo -e "This script will install ${GREEN}PaSSHport${NC} on a fresh Debian 11 (Bullseye)." echo echo 'This script will:' echo '- install PaSSHport Python dependancies' echo '- install a venv (virtualenv for PaSSHport dependancies execution)' echo '- add a "passhport" system user' echo '- add a local postgresql installation and link passhport to it' echo '- add a local apache with wsgi to run passhport service' echo '- create various directories to store conf, log and databases' echo echo -e "${RED}Be warned that this script needs to be run on a fresh system, no guarantees here" echo echo -e "${BLUE}If you want to ${RED}remove${BLUE} passhportd from this system, run this script with option '-p'.${NC}" echo '' if [ ${INTERACTIVE} -eq 1 ] then echo -e "${BLUE}Once you read and understood the above lines, you may proceed by typing" echo -e "'${GREEN}yes${BLUE}', or exit by the famous '${RED}CTRL+C${BLUE}' :${NC}" read ANSWER; else ANSWER='yes' fi while [ "${ANSWER}" != 'yes' ] do echo -e "${BLUE}Please type excatly "${GREEN}yes${BLUE}" or exit by pressing '${RED}CTRL+C${BLUE}'.${NC}" read ANSWER done # First we install packages install_packages # We create the passhport user create_passhport_user # Unless we're building a docker image, we'll need to download the sources if [ ${DOCKER_INSTALL} -ne 1 ] then download_sources fi # Configure the initial system initial_config # Creating Python virtual-env create_python_venv # Unless we're building a docker image, we'll need to # - generate SSH keys (to be put later into all targets) # - configure bash_completion # - create SSL certs # - populate database if [ $DOCKER_INSTALL -ne 1 ] then generate_ssh_keys install_bash_completion generate_ssl_certs configure_postgresql initial_configuration fi # Configure apache configure_apache_for_passhportd configure_apache_for_passhweb # Initial configuration if [ $DOCKER_INSTALL -ne 1 ] then initial_configuration fi } ##### MAIN ##### while getopts "sdb:p" OPTION do case ${OPTION} in s) INTERACTIVE=0 ;; b) GITBRANCH=${OPTARG} ;; p) purge exit 0 ;; d) DOCKER_INSTALL=1 ;; *) echo "Unknown option, exiting..." exit 1 ;; # DEFAULT esac done install