diff --git a/1-setup.sh b/1-setup.sh index 3b06e30..3284199 100644 --- a/1-setup.sh +++ b/1-setup.sh @@ -11,7 +11,7 @@ # If something isn't working? # tail -f /var/log/syslog /var/log/tomcat*/*.out /var/log/mysql/*.log -# This whole install routine could be collated into one huge script, but it is far easer to manage and maintan by +# This whole install routine could be collated into one huge script, but it is far easer to manage and maintan by # breaking up the different stages of the install into at least 4 separate scripts as follows... # 1-setup.sh is a central script that manages all inputs, options and sequences other included 'install' scripts. # 2-install-guacamole is the main guts of the whole build. This script downloads and builds Guacamole from source. @@ -19,11 +19,6 @@ # 4a-install-self-signed-nginx.sh sets up the new Nginx/Guacamole front end with self signed SSL certificates. # 4b-install-ssl-letsencrypt-nginx.sh sets up Nginx with public SSL certificates from LetsEncrypt. - -####################################################################################################################### -# Initial enviromment setup ########################################################################################### -####################################################################################################################### - clear # Prepare text output colours @@ -44,37 +39,34 @@ MAGENTA='\033[0;35m' LMAGENTA='\033[0;95m' NC='\033[0m' #No Colour +# Check to see if previous build/install files exist, stop and check to be safe. +if [ "$( find . -maxdepth 1 \( -name 'guacamole-*' -o -name 'mysql-connector-java-*' \) )" != "" ]; then +# Script branding header +echo + echo -e "${GREYB}Itiligent Virtual Desktop Appliance Setup." + echo -e " ${LGREEN}Powered by Guacamole" + echo + echo + echo -e "${RED}Possible previous temp files detected in current build path. Please review and remove old 'guacamole-*' & 'mysql-connector-java-*' files before proceeding.${GREY}" 1>&2 + echo +exit 1 +fi + +####################################################################################################################### +# Core setup ########################################################################################################## +####################################################################################################################### + #Setup download and temp directory paths USER_HOME_DIR=$(eval echo ~${SUDO_USER}) -DOWNLOAD_DIR=$USER_HOME_DIR/guac-setup +DOWNLOAD_DIR=$USER_HOME_DIR/guacamole DB_BACKUP_DIR=$USER_HOME_DIR/mysqlbackups/ TMP_DIR=$DOWNLOAD_DIR/tmp -source /etc/os-release -OS_FLAVOUR=$ID -OS_VERSION=$VERSION -JPEGTURBO="" -LIBPNG="" - -# Announce the script we're running -echo -echo -e "${GREYB}Itiligent Jump Server Appliance Setup." -echo -e " ${LGREEN}Powered by Guacamole" -echo - -# Setup directory locations -mkdir -p $DOWNLOAD_DIR -mkdir -p $DB_BACKUP_DIR -mkdir -p $TMP_DIR - -# Now prompt for sudo and set dir permissions so both sudo and non sudo functions can access tmp setup files -sudo chmod -R 770 $TMP_DIR -sudo chown -R $SUDO_USER:root $TMP_DIR # Github download branch GITHUB="https://raw.githubusercontent.com/itiligent/Guacamole-Setup/main/" #Version of Guacamole to install -GUAC_VERSION="1.5.0" +GUAC_VERSION="1.5.1" # Set preferred Apache CDN download link GUAC_SOURCE_LINK="http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/${GUAC_VERSION}" @@ -91,49 +83,64 @@ LOG_LOCATION="${DOWNLOAD_DIR}/guacamole_${GUAC_VERSION}_setup.log" # Guacamole default install URL GUAC_URL=http://localhost:8080/guacamole/ -# Non interactive silent setup options - add true/false or specific values -SERVER_NAME="" # Preferred server hostname -INSTALL_MYSQL="" # Install locally true/false -SECURE_MYSQL="" # Apply mysql secure configurarion tool -MYSQL_HOST="" # leave blank for localhost default, only specify for remote servers -MYSQL_PORT="" # If blank default is 3306 -GUAC_DB="" # If blank default is guacamole_db -GUAC_USER="" # if blank default is guacamole_user -GUAC_PWD="" # Should not be blank as this may break some aspects of install -MYSQL_ROOT_PWD="" # Should not be blank as this may break some aspects of install -INSTALL_TOTP="" # TOTP MFA extension -INSTALL_DUO="" # DUO MFA extension (cant be installed simultaneously with TOTP) -INSTALL_LDAP="" # Active Directory extension -INSTALL_NGINX="" # Install and configure Guacamole behind Nginx reverse proxy (http port 80 only) -PROXY_SITE="" # Local DNS name for reverse proxy and self signed ssl certificates -SELF_SIGNED="" # Add self signed SSL support to Nginx (Let's Encrypt not available) -INSTALL_LETS_ENCRYPT="" # Add Lets Encrypt public SSL support for Nginx (self signed SSL certs not available) -LE_DNS_NAME="" # Public DNS name to bind with Lets Encrypt certificates -LE_EMAIL="webmaster@itiligent.com" # Webmaster/admin email for Lets Encrypt -EMAIL_DOMAIN="itiligent.com" # Email relay domain for backup notifications -ALERT_EMAIL="alerts@itiligent.com" # Email address for backup notifications -BACKUP_RETAIN_DAYS="30" # How long to keep backups for -CERT_COUNTRY="AU" # 2 coutry charater code only, must not be blank -CERT_STATE="Victoria" # Optional to change, must not be blank -CERT_LOCATION="Melbourne" # Optional to change, must not be blank -CERT_ORG="Itiligent" # Optional to change, must not be blank -CERT_OU="I.T." # Optional to change, must not be blank -CERT_DAYS="3650" # Number of days until self signed certificate expiry +# Depending on the Linux distro, required libraries have varied names. Standardising with names makes adapting +# to other distros easier. +source /etc/os-release +OS_FLAVOUR=$ID +OS_VERSION=$VERSION +JPEGTURBO="" +LIBPNG="" + +# Get the default route interface IP +DEFAULT_IP=$(ip addr show $(ip route | awk '/default/ { print $5 }') | grep "inet" | head -n 1 | awk '/inet/ {print $2}' | cut -d'/' -f1) -# We need to try and grab a default value for the local FQDN. Domain search suffix is used in this case becausue -# this is the simplest common default resolv.conf value available between recent Debian and Ubuntu flavours. YMMV. +# Get an intital search suffix for use as a starting default local dns domain prompt value, we change this later DOMAIN_SEARCH_SUFFIX=$(grep search /etc/resolv.conf | grep -v "#" | sed 's/'search[[:space:]]'//') -DEFAULT_FQDN=$HOSTNAME.$DOMAIN_SEARCH_SUFFIX -# Finally we check to prevent reinstalling over the current from possibly older/previous versions of build files. -if [ "$( find . -maxdepth 2 \( -name 'guacamole-*' -o -name 'mysql-connector-java-*' \) )" != "" ]; then - echo -e "${RED}Possible previous temp files detected in current build path. Please review and remove old 'guacamole-*' & 'mysql-connector-java-*' files before proceeding.${GREY}" 1>&2 -exit 1 -fi +####################################################################################################################### +# Silent setup options - adding true/false or specific values below prevents prompt at install ######################## +####################################################################################################################### +SERVER_NAME="" # Preferred server hostname +LOCAL_DOMAIN="" # Local DNS space in use +INSTALL_MYSQL="" # Install locally true/false +SECURE_MYSQL="" # Apply mysql secure configurarion tool +MYSQL_HOST="" # leave blank for localhost default, only specify for remote servers +MYSQL_PORT="" # If blank default is 3306 +GUAC_DB="" # If blank default is guacamole_db +GUAC_USER="" # if blank default is guacamole_user +GUAC_PWD="" # Should not be blank as this may break some aspects of install +MYSQL_ROOT_PWD="" # Should not be blank as this may break some aspects of install +INSTALL_TOTP="" # TOTP MFA extension +INSTALL_DUO="" # DUO MFA extension (cant be installed simultaneously with TOTP) +INSTALL_LDAP="" # Active Directory extension +INSTALL_NGINX="" # Install and configure Guacamole behind Nginx reverse proxy (http port 80 only) +PROXY_SITE="" # Local DNS name for reverse proxy and self signed ssl certificates +SELF_SIGN="" # Add self signed SSL support to Nginx (Let's Encrypt not available) +CERT_COUNTRY="AU" # 2 coutry charater code only, must not be blank +CERT_STATE="Victoria" # Optional to change, must not be blank +CERT_LOCATION="Melbourne" # Optional to change, must not be blank +CERT_ORG="Itiligent" # Optional to change, must not be blank +CERT_OU="I.T." # Optional to change, must not be blank +CERT_DAYS="3650" # Number of days until self signed certificate expiry +LETS_ENCRYPT="" # Add Lets Encrypt public SSL support for Nginx (self signed SSL certs not available) +LE_DNS_NAME="" # Public DNS name to bind with Lets Encrypt certificates +LE_EMAIL="" # Webmaster/admin email for Lets Encrypt +BACKUP_EMAIL="" # Email address for backup notifications +BACKUP_RETENTION="30" # How many days to keep backups for + +# Script branding header +echo +echo -e "${GREYB}Itiligent Virtual Desktop Appliance Setup." +echo -e " ${LGREEN}Powered by Guacamole" +echo +# Setup directory locations +mkdir -p $DOWNLOAD_DIR +mkdir -p $DB_BACKUP_DIR +mkdir -p $TMP_DIR ####################################################################################################################### -# Download github setup scripts ####################################################################################### +# Download github setup scripts. To prevent overwrite, comment out lines of any scripts you have edited. ############## ####################################################################################################################### # Download config scripts and setup items from github @@ -144,88 +151,143 @@ wget -q --show-progress ${GITHUB}2-install-guacamole.sh -O 2-install-guacamole.s wget -q --show-progress ${GITHUB}3-install-nginx.sh -O 3-install-nginx.sh wget -q --show-progress ${GITHUB}4a-install-ssl-self-signed-nginx.sh -O 4a-install-ssl-self-signed-nginx.sh wget -q --show-progress ${GITHUB}4b-install-ssl-letsencrypt-nginx.sh -O 4b-install-ssl-letsencrypt-nginx.sh - -# Grab Guacamole auth extension config scripts +# Grab Guacamole manually run add on scripts wget -q --show-progress ${GITHUB}add-auth-duo.sh -O add-auth-duo.sh wget -q --show-progress ${GITHUB}add-auth-ldap.sh -O add-auth-ldap.sh wget -q --show-progress ${GITHUB}add-auth-totp.sh -O add-auth-totp.sh - - +wget -q --show-progress ${GITHUB}add-smtp-relay-o365.sh -O add-smtp-relay-o365.sh # Grab backup and security hardening scripts wget -q --show-progress ${GITHUB}backup-guac.sh -O backup-guac.sh wget -q --show-progress ${GITHUB}add-ssl-guac-gaucd.sh -O add-ssl-guac-gaucd.sh wget -q --show-progress ${GITHUB}add-fail2ban.sh -O add-fail2ban.sh - # Grab a (customisable) branding extension wget -q --show-progress ${GITHUB}branding.jar -O branding.jar chmod +x *.sh +sleep 2 +clear + +# Script branding header +echo +echo -e "${GREYB}Itiligent Virtual Desktop Appliance Setup." +echo -e " ${LGREEN}Powered by Guacamole" +echo +echo + +# For convenience & sanity check, diplay status of preset script options at start of install +echo -e "${GREY}Enabled non-interactive presets are listed below, blank entries will prompt." +echo -e "${DGREY}Server host name\t= ${GREY}${SERVER_NAME}" +echo -e "${DGREY}Local DNS Domain\t= ${GREY}${LOCAL_DOMAIN}" +echo -e "${DGREY}Install MYSQL locally\t= ${GREY}${INSTALL_MYSQL}" +echo -e "${DGREY}MySQL secure install\t= ${GREY}${SECURE_MYSQL}" +echo -e "${DGREY}MySQL remote IP\t\t= ${GREY}${MYSQL_HOST}" +echo -e "${DGREY}MySQL port\t\t= ${GREY}${MYSQL_PORT}" +echo -e "${DGREY}Guacamole db name\t= ${GREY}${GUAC_DB}" +echo -e "${DGREY}Guacamole db user name\t= ${GREY}${GUAC_USER}" +echo -e "${DGREY}Guacamole user pwd\t= ${GREY}${GUAC_PWD}" +echo -e "${DGREY}MySQL root pwd\t\t= ${GREY}${MYSQL_ROOT_PWD}" +echo -e "${DGREY}Add TOTP\t\t= ${GREY}${INSTALL_TOTP}" +echo -e "${DGREY}Add DUO\t\t\t= ${GREY}${INSTALL_DUO}" +echo -e "${DGREY}Add LDAP\t\t= ${GREY}${INSTALL_LDAP}${GREY}" +echo -e "${DGREY}Install Nginx rev proxy\t= ${GREY}${INSTALL_NGINX}${GREY}" +echo -e "${DGREY}Proxy local DNS name\t= ${GREY}${PROXY_SITE}" +echo -e "${DGREY}Add self signed SSL\t= ${GREY}${SELF_SIGN}${GREY}" +echo -e "${DGREY}Self sign cert days\t= ${GREY}${CERT_DAYS}${GREY}" +echo -e "${DGREY}Self sign country\t= ${GREY}${CERT_COUNTRY}${GREY}" +echo -e "${DGREY}Self sign state\t\t= ${GREY}${CERT_STATE}${GREY}" +echo -e "${DGREY}Self sign location\t= ${GREY}${CERT_LOCATION}${GREY}" +echo -e "${DGREY}Self sign ORG\t\t= ${GREY}${CERT_ORG}${GREY}" +echo -e "${DGREY}Self sign OU\t\t= ${GREY}${CERT_OU}${GREY}" +echo -e "${DGREY}Add Let's Encrypt SSL\t= ${GREY}${LETS_ENCRYPT}${GREY}" +echo -e "${DGREY}Let's Encrypt FQDN\t= ${GREY}${LE_DNS_NAME}${GREY}" +echo -e "${DGREY}Let's Encrypt email\t= ${GREY}${LE_EMAIL}${GREY}" +echo -e "${DGREY}Backup notify email\t= ${GREY}${BACKUP_EMAIL}${GREY}" +echo -e "${DGREY}Days to keep backups\t= ${GREY}${BACKUP_RETENTION}${GREY}" + +# Pause to optionally customise downloaded scripts before any install actions +echo +echo -e "${LYELLOW}Ctrl+Z now to exit if you wish to set any above options for an unattended install." +echo -e "${LYELLOW}After editing the setup script, you must always run it locally (not as sudo) i.e ./1-setup.sh (not from the web link)." + +# Now prompt for sudo to get ready for a hostname change or so both sudo and non sudo functions can access tmp setup files +echo -e "${LGREEN}" +sudo chmod -R 770 $TMP_DIR +sudo chown -R $SUDO_USER:root $TMP_DIR ####################################################################################################################### # Begin install menu prompts ########################################################################################## ####################################################################################################################### -# We need a default hostname avaiable to apply even if we do not want to change the hostname. This approach allows the -# user to simply hit enter at the prompt without this creating a blank entry into the /etc/hosts file. +# We need a default hostname available to apply even if we do not want to change the hostname. This approach allows the +# user to simply hit enter at the prompt without this creating a blank entry into the /etc/hosts file. # Hostnames and matching DNS entries are essential for implementing SSL succesfully. echo -echo if [[ -z ${SERVER_NAME} ]]; then echo -e "${LYELLOW}Update Linux system HOSTNAME [Enter to keep: ${HOSTNAME}]${LGREEN}" read -p " Enter new HOSTNAME : " SERVER_NAME if [[ "${SERVER_NAME}" = "" ]]; then SERVER_NAME=$HOSTNAME + fi echo sudo hostnamectl set-hostname $SERVER_NAME &>> ${LOG_LOCATION} sudo sed -i '/127.0.1.1/d' /etc/hosts &>> ${LOG_LOCATION} echo '127.0.1.1 '${SERVER_NAME}'' | sudo tee -a /etc/hosts &>> ${LOG_LOCATION} sudo systemctl restart systemd-hostnamed &>> ${LOG_LOCATION} - else + else echo sudo hostnamectl set-hostname $SERVER_NAME &>> ${LOG_LOCATION} sudo sed -i '/127.0.1.1/d' /etc/hosts &>> ${LOG_LOCATION} echo '127.0.1.1 '${SERVER_NAME}'' | sudo tee -a /etc/hosts &>> ${LOG_LOCATION} sudo systemctl restart systemd-hostnamed &>> ${LOG_LOCATION} fi -fi + + +echo +if [[ -z ${LOCAL_DOMAIN} ]]; then + echo -e "${LYELLOW}Update Linux LOCAL DNS DOMAIN [Enter to keep: .${DOMAIN_SEARCH_SUFFIX}]${LGREEN}" + read -p " Enter LOCAL DOMAIN NAME: " LOCAL_DOMAIN + if [[ "${LOCAL_DOMAIN}" = "" ]]; then + LOCAL_DOMAIN=$DOMAIN_SEARCH_SUFFIX + fi + echo + sudo sed -i "/${DEFAULT_IP}/d" /etc/hosts + sudo sed -i '/domain/d' /etc/resolv.conf + sudo sed -i '/search/d' /etc/resolv.conf + # Update the /etc/hosts file with the new domain values + echo ''${DEFAULT_IP}' '${SERVER_NAME}.${LOCAL_DOMAIN} ${SERVER_NAME}'' | sudo tee -a /etc/hosts &>> ${LOG_LOCATION} + #Update resolv.conf with new domain and search suffix values + echo 'domain '${LOCAL_DOMAIN}'' | sudo tee -a /etc/resolv.conf &>> ${LOG_LOCATION} + echo 'search '${LOCAL_DOMAIN}'' | sudo tee -a /etc/resolv.conf &>> ${LOG_LOCATION} + sudo systemctl restart systemd-hostnamed &>> ${LOG_LOCATION} + else + echo + sudo sed -i "/${DEFAULT_IP}/d" /etc/hosts + sudo sed -i '/domain/d' /etc/resolv.conf + sudo sed -i '/search/d' /etc/resolv.conf + # Update the /etc/hosts file with the new domain values + echo ''${DEFAULT_IP}' '${SERVER_NAME}.${LOCAL_DOMAIN} ${SERVER_NAME}'' | sudo tee -a /etc/hosts &>> ${LOG_LOCATION} + #Update resolv.conf with new domain and search suffix values + echo 'domain '${LOCAL_DOMAIN}'' | sudo tee -a /etc/resolv.conf &>> ${LOG_LOCATION} + echo 'search '${LOCAL_DOMAIN}'' | sudo tee -a /etc/resolv.conf &>> ${LOG_LOCATION} + sudo systemctl restart systemd-hostnamed &>> ${LOG_LOCATION} + fi + +# After updateing the hostname and domain names, we can now use a refreshed value for the local FQDN. +DEFAULT_FQDN=$SERVER_NAME.$LOCAL_DOMAIN clear + +# Script branding header echo -# For convenience & sanity check, diplay status of preset script options at start of install -echo -e "${GREY}Enabled non-interactive presets are listed below, blank entries will prompt." -echo -e "(Ctrl+C to exit & edit 1-setup.sh before continuning.)" -echo -e "${DGREY}Server host name\t= ${GREY}${SERVER_NAME}" -echo -e "${DGREY}Install MYSQL locally\t= ${GREY}${INSTALL_MYSQL}" -echo -e "${DGREY}MySQL secure install\t= ${GREY}${SECURE_MYSQL}" -echo -e "${DGREY}MySQL hostname/IP\t= ${GREY}${MYSQL_HOST}" -echo -e "${DGREY}MySQL port\t\t= ${GREY}${MYSQL_PORT}" -echo -e "${DGREY}Guacamole db name\t= ${GREY}${GUAC_DB}" -echo -e "${DGREY}Guacamole db user name\t= ${GREY}${GUAC_USER}" -echo -e "${DGREY}Guacamole user pwd\t= ${GREY}${GUAC_PWD}" -echo -e "${DGREY}MySQL root pwd\t\t= ${GREY}${MYSQL_ROOT_PWD}" -echo -e "${DGREY}Install TOTP\t\t= ${GREY}${INSTALL_TOTP}" -echo -e "${DGREY}Install DUO\t\t= ${GREY}${INSTALL_DUO}" -echo -e "${DGREY}Install LDAP\t\t= ${GREY}${INSTALL_LDAP}${GREY}" -echo -e "${DGREY}Install Nginx rev proxy\t= ${GREY}${INSTALL_NGINX}${GREY}" -echo -e "${DGREY}Proxy local DNS name\t= ${GREY}${PROXY_SITE}" -echo -e "${DGREY}Add self signed SSL\t= ${GREY}${SELF_SIGNED}${GREY}" -echo -e "${DGREY}Add Let's Encrypt SSL\t= ${GREY}${INSTALL_LETS_ENCRYPT}${GREY}" -echo -e "${DGREY}Let's Encrypt pub FQDN\t= ${GREY}${LE_DNS_NAME}${GREY}" -echo -e "${DGREY}Let's Encrypt email\t= ${GREY}${LE_EMAIL}${GREY}" -echo -e "${DGREY}SMTP relay domain\t= ${GREY}${EMAIL_DOMAIN}${GREY}" -echo -e "${DGREY}Alerts email address\t= ${GREY}${ALERT_EMAIL}${GREY}" -echo -e "${DGREY}Days to keep backups\t= ${GREY}${BACKUP_RETAIN_DAYS}${GREY}" -echo -e "${DGREY}Self signed cert days\t= ${DGREY}${CERT_DAYS}${GREY}" -echo -e "${DGREY}Self signed country\t= ${DGREY}${CERT_COUNTRY}${GREY}" -echo -e "${DGREY}Self signed state\t= ${DGREY}${CERT_STATE}${GREY}" -echo -e "${DGREY}Self signed location\t= ${DGREY}${CERT_LOCATION}${GREY}" -echo -e "${DGREY}Self signed ORG\t\t= ${DGREY}${CERT_ORG}${GREY}" -echo -e "${DGREY}Self signed OU\t\t= ${DGREY}${CERT_OU}${GREY}" - -# Prompt the user to see if they would like to install MySQL, default of yes +echo -e "${GREYB}Itiligent Virtual Desktop Appliance Setup." +echo -e " ${LGREEN}Powered by Guacamole" +echo +echo + +echo -e "${LGREEN}MySQL setup options:${GREY}" +# Prompt the user to install MySQL, default of yes if [[ -z ${INSTALL_MYSQL} ]]; then - echo - echo -e -n "${LGREEN}SQL: Install MySQL? (for a remote MySQL Server select 'n') (y/n) [default y]: ${GREY}" + echo -e -n "SQL: Install MySQL? (for a remote MySQL Server select 'n') (y/n) [default y]: ${GREY}" read PROMPT if [[ ${PROMPT} =~ ^[Nn]$ ]]; then INSTALL_MYSQL=false @@ -234,7 +296,7 @@ if [[ -z ${INSTALL_MYSQL} ]]; then fi fi -# Prompt the user to see if they would like to apply the Mysql secure installation +# Prompt the user to apply the Mysql secure installation locally if [ -z ${SECURE_MYSQL} ] && [ "${INSTALL_MYSQL}" = true ]; then echo -e -n "${GREY}SQL: Apply MySQL secure installation settings to LOCAL db? (y/n) [default y]: ${GREY}" read PROMPT @@ -245,7 +307,7 @@ if [ -z ${SECURE_MYSQL} ] && [ "${INSTALL_MYSQL}" = true ]; then fi fi -# Prompt the user to see if they would like to apply the Mysql secure installation +# Prompt the user to apply the Mysql secure installation to remote db if [ -z ${SECURE_MYSQL} ] && [ "${INSTALL_MYSQL}" = false ]; then echo -e -n "${GREY}SQL: Apply MySQL secure installation settings to REMOTE db? (y/n) [default n]: ${GREY}" read PROMPT @@ -256,8 +318,8 @@ if [ -z ${SECURE_MYSQL} ] && [ "${INSTALL_MYSQL}" = false ]; then fi fi +# We need to get some additional MYSQL values if [ "${INSTALL_MYSQL}" = false ]; then - # We need to get some additional MYSQL values [ -z "${MYSQL_HOST}" ] \ && read -p "SQL: Enter MySQL server hostname or IP: " MYSQL_HOST [ -z "${MYSQL_PORT}" ] \ @@ -288,6 +350,18 @@ if [ -z "${GUAC_USER}" ]; then GUAC_USER="guacamole_user" fi +# Get Guacamole User password, confirm correct password entry and prevent blank passwords +if [ -z "${GUAC_PWD}" ]; then + while true; do + read -s -p "SQL: Enter ${MYSQL_HOST}'s MySQL ${GUAC_USER} password: " GUAC_PWD + echo + read -s -p "SQL: Confirm ${MYSQL_HOST}'s MySQL ${GUAC_USER} password: " PROMPT2 + echo + [ "${GUAC_PWD}" = "${PROMPT2}" ] && [ "${GUAC_PWD}" != "" ] && [ "${PROMPT2}" != "" ] && break + echo -e "${RED}Passwords don't match or can't be null. Please try again.${GREY}" 1>&2 + done +fi + # Get MySQL root password, confirm correct password entry and prevent blank passwords if [ -z "${MYSQL_ROOT_PWD}" ]; then while true; do @@ -300,21 +374,27 @@ if [ -z "${MYSQL_ROOT_PWD}" ]; then done fi -# Get Guacamole User password, confirm correct password entry and prevent blank passwords -if [ -z "${GUAC_PWD}" ]; then +# Prompt for preferred backup notification email address +if [[ -z ${BACKUP_EMAIL} ]]; then while true; do - read -s -p "SQL: Enter ${MYSQL_HOST}'s MySQL ${GUAC_USER} password: " GUAC_PWD - echo - read -s -p "SQL: Confirm ${MYSQL_HOST}'s MySQL ${GUAC_USER} password: " PROMPT2 - echo - [ "${GUAC_PWD}" = "${PROMPT2}" ] && [ "${GUAC_PWD}" != "" ] && [ "${PROMPT2}" != "" ] && break - echo -e "${RED}Passwords don't match or can't be null. Please try again.${GREY}" 1>&2 + read -p "SQL: Enter email address for SQL backup messages [Enter to skip]: " BACKUP_EMAIL + [ "${BACKUP_EMAIL}" = "" ] || [ "${BACKUP_EMAIL}" != "" ] && break + # Rather than allow a blank value, uncomment to alternately force user to enter an explicit value instead + # [ "${BACKUP_EMAIL}" != "" ] && break + # echo -e "${RED}You must enter a proxy site DNS name. Please try again.${GREY}" 1>&2 done fi +# If no backup notification email address is given, enter a default value +if [ -z ${BACKUP_EMAIL} ]; then +BACKUP_EMAIL="backup-email@yourdomain.com" +fi + +echo +echo -e "${LGREEN}Guacamole authentication extension options:${GREY}" # Prompt the user if they would like to install TOTP MFA, default of no if [[ -z "${INSTALL_TOTP}" ]] && [[ "${INSTALL_DUO}" != true ]]; then - echo -e -n "${GREY}GUAC MFA: Install TOTP? (choose 'n' if you want Duo) (y/n)? [default n]: " + echo -e -n "AUTH: Install TOTP? (choose 'n' if you want Duo) (y/n)? [default n]: " read PROMPT if [[ ${PROMPT} =~ ^[Yy]$ ]]; then INSTALL_TOTP=true @@ -326,7 +406,7 @@ fi # Prompt the user if they would like to install Duo MFA, default of no if [[ -z "${INSTALL_DUO}" ]] && [[ "${INSTALL_TOTP}" != true ]]; then - echo -e -n "${GREY}GUAC MFA: Install Duo? (y/n) [default n]: " + echo -e -n "${GREY}AUTH: Install Duo? (y/n) [default n]: " read PROMPT if [[ ${PROMPT} =~ ^[Yy]$ ]]; then INSTALL_DUO=true @@ -336,7 +416,7 @@ if [[ -z "${INSTALL_DUO}" ]] && [[ "${INSTALL_TOTP}" != true ]]; then fi fi -# We can't install TOTP and Duo at the same time, option not supported by Guacamole... +# We can't install TOTP and Duo at the same time (option not supported by Guacamole) if [[ "${INSTALL_TOTP}" = true ]] && [[ "${INSTALL_DUO}" = true ]]; then echo -e "${RED}GUAC MFA: TOTP and Duo cannot be installed at the same time.${GREY}" 1>&2 exit 1 @@ -344,7 +424,7 @@ fi # Prompt the user if they would like to install Duo MFA, default of no if [[ -z "${INSTALL_LDAP}" ]]; then - echo -e -n "${GREY}GUAC AUTH: Install LDAP? (y/n) [default n]: " + echo -e -n "${GREY}AUTH: Install LDAP? (y/n) [default n]: " read PROMPT if [[ ${PROMPT} =~ ^[Yy]$ ]]; then INSTALL_LDAP=true @@ -353,9 +433,11 @@ if [[ -z "${INSTALL_LDAP}" ]]; then fi fi +echo +echo -e "${LGREEN}Nginx reverse proxy options:${GREY}" # Prompt for Guacamole front end reverse proxy option if [[ -z ${INSTALL_NGINX} ]]; then - echo -e -n "${LGREEN}ADD REVERSE PROXY?: Protect Gucamole behind Nginx reverse proxy (y/n)? [default y]: ${GREY}" + echo -e -n "REV PROXY: Protect Gucamole behind Nginx reverse proxy (y/n)? [default y]: " read PROMPT if [[ ${PROMPT} =~ ^[Nn]$ ]]; then INSTALL_NGINX=false @@ -367,9 +449,9 @@ fi # We must assign a DNS name for the new proxy site if [[ -z ${PROXY_SITE} ]] && [[ "${INSTALL_NGINX}" = true ]]; then while true; do - read -p "REVERSE PROXY NAME?: Enter proxy local DNS name? [Enter to use ${DEFAULT_FQDN}]: " PROXY_SITE + read -p "REV PROXY: Enter proxy local DNS name? [Enter to use ${DEFAULT_FQDN}]: " PROXY_SITE [ "${PROXY_SITE}" = "" ] || [ "${PROXY_SITE}" != "" ] && break - # rather than allow any default, alternately force user to enter an explicit name instead + # Rather than allow the default value below, uncomment to alternately force user to enter an explicit name instead # [ "${PROXY_SITE}" != "" ] && break # echo -e "${RED}You must enter a proxy site DNS name. Please try again.${GREY}" 1>&2 done @@ -381,19 +463,19 @@ PROXY_SITE="${DEFAULT_FQDN}" fi # Prompt for self signed SSL reverse proxy option -if [[ -z ${SELF_SIGNED} ]] && [[ "${INSTALL_NGINX}" = true ]]; then +if [[ -z ${SELF_SIGN} ]] && [[ "${INSTALL_NGINX}" = true ]]; then # Prompt the user to see if they would like to install self signed SSL support for Nginx, default of no - echo -e -n "${GREY}PROXY SSL?: Add self signed SSL support to Nginx? (y/n)? (choose 'n' for Let's Encrypt)[default n]: " + echo -e -n "REV PROXY: Add self signed SSL support to Nginx? (y/n)? (choose 'n' for Let's Encrypt)[default n]: " read PROMPT if [[ ${PROMPT} =~ ^[Yy]$ ]]; then - SELF_SIGNED=true + SELF_SIGN=true else - SELF_SIGNED=false + SELF_SIGN=false fi fi -# Prompt to assign the self sign SSL certficate a custom expiry date, uncomment to force a manual entry -#if [ "${SELF_SIGNED}" = true ]; then +# Optional prompt to assign the self sign SSL certficate a custom expiry date, uncomment to force a manual entry +#if [ "${SELF_SIGN}" = true ]; then # read - p "PROXY: Enter number of days till SSL certificate expires [default 3650]: " CERT_DAYS #fi @@ -403,29 +485,29 @@ if [ -z "${CERT_DAYS}" ]; then fi # Prompt for Let's Encrypt SSL reverse proxy configuration option -if [[ -z ${INSTALL_LETS_ENCRYPT} ]] && [[ "${INSTALL_NGINX}" = true ]] && [[ "${SELF_SIGNED}" = "false" ]]; then - echo -e -n "${GREY}SSL PROXY: Add Let's Encrypt SSL support to Nginx reverse proxy (y/n) [default n]: ${GREY}" +if [[ -z ${LETS_ENCRYPT} ]] && [[ "${INSTALL_NGINX}" = true ]] && [[ "${SELF_SIGN}" = "false" ]]; then + echo -e -n "REV PROXY: Add Let's Encrypt SSL support to Nginx reverse proxy (y/n) [default n]: ${GREY}" read PROMPT if [[ ${PROMPT} =~ ^[Yy]$ ]]; then - INSTALL_LETS_ENCRYPT=true + LETS_ENCRYPT=true else - INSTALL_LETS_ENCRYPT=false + LETS_ENCRYPT=false fi fi # Prompt for Let's Encrypt public dns name -if [[ -z ${LE_DNS_NAME} ]] && [[ "${INSTALL_LETS_ENCRYPT}" = true ]]; then +if [[ -z ${LE_DNS_NAME} ]] && [[ "${LETS_ENCRYPT}" = true ]]; then while true; do - read -p "Enter the FQDN for your public proxy site : " LE_DNS_NAME + read -p "REV PROXY: Enter the FQDN for your public proxy site : " LE_DNS_NAME [ "${LE_DNS_NAME}" != "" ] && break echo -e "${RED}You must enter a public DNS name. Please try again.${GREY}" 1>&2 done fi # Prompt for Let's Encrypt admin email -if [[ -z ${LE_EMAIL} ]] && [[ "${INSTALL_LETS_ENCRYPT}" = true ]]; then +if [[ -z ${LE_EMAIL} ]] && [[ "${LETS_ENCRYPT}" = true ]]; then while true; do - read -p "Enter the email address for Let's Encrypt notifications : " LE_EMAIL + read -p "REV PROXY: Enter the email address for Let's Encrypt notifications : " LE_EMAIL [ "${LE_EMAIL}" != "" ] && break echo -e "${RED}You must enter an email address. Please try again.${GREY}" 1>&2 done @@ -437,6 +519,8 @@ fi ####################################################################################################################### # Ubuntu and Debian each require different dependency packages. Below works ok from Ubuntu 18.04 / Debian 10 and above. +# To adapt this script to other distros, research the correct library package names and reference these with the varible +# names assigned here. See https://guacamole.apache.org/doc/gug/installing-guacamole.html for dependecy info. echo -e "${GREY}Checking linux distro specific dependencies..." if [[ $OS_FLAVOUR == "ubuntu" ]] || [[ $OS_FLAVOUR == "ubuntu"* ]]; then # potentially expand out distro choices here JPEGTURBO="libjpeg-turbo8-dev" @@ -454,15 +538,16 @@ else fi # Because the below scripts may be run manually after install, we need to sync them -# with global variables or setup prompt options. +# with our global variables or any setup prompt choices we make. This way we can run them +# later and they will all work as a set without any manual changes. sed -i "s|MYSQL_HOST=|MYSQL_HOST='${MYSQL_HOST}'|g" $DOWNLOAD_DIR/backup-guac.sh sed -i "s|MYSQL_PORT=|MYSQL_PORT='${MYSQL_PORT}'|g" $DOWNLOAD_DIR/backup-guac.sh sed -i "s|GUAC_USER=|GUAC_USER='${GUAC_USER}'|g" $DOWNLOAD_DIR/backup-guac.sh sed -i "s|GUAC_PWD=|GUAC_PWD='${GUAC_PWD}'|g" $DOWNLOAD_DIR/backup-guac.sh sed -i "s|GUAC_DB=|GUAC_DB='${GUAC_DB}'|g" $DOWNLOAD_DIR/backup-guac.sh sed -i "s|DB_BACKUP_DIR=|DB_BACKUP_DIR='${DB_BACKUP_DIR}'|g" $DOWNLOAD_DIR/backup-guac.sh -sed -i "s|ALERT_EMAIL=|ALERT_EMAIL='${ALERT_EMAIL}'|g" $DOWNLOAD_DIR/backup-guac.sh -sed -i "s|BACKUP_RETAIN_DAYS=|BACKUP_RETAIN_DAYS='${BACKUP_RETAIN_DAYS}'|g" $DOWNLOAD_DIR/backup-guac.sh +sed -i "s|BACKUP_EMAIL=|BACKUP_EMAIL='${BACKUP_EMAIL}'|g" $DOWNLOAD_DIR/backup-guac.sh +sed -i "s|BACKUP_RETENTION=|BACKUP_RETENTION='${BACKUP_RETENTION}'|g" $DOWNLOAD_DIR/backup-guac.sh sed -i "s|GUAC_VERSION=|GUAC_VERSION='${GUAC_VERSION}'|g" $DOWNLOAD_DIR/add-auth-duo.sh sed -i "s|GUAC_VERSION=|GUAC_VERSION='${GUAC_VERSION}'|g" $DOWNLOAD_DIR/add-auth-ldap.sh sed -i "s|GUAC_VERSION=|GUAC_VERSION='${GUAC_VERSION}'|g" $DOWNLOAD_DIR/add-auth-totp.sh @@ -470,7 +555,12 @@ sed -i "s|TOMCAT_VERSION=|TOMCAT_VERSION='${TOMCAT_VERSION}'|g" $DOWNLOAD_DIR/ad sed -i "s|TOMCAT_VERSION=|TOMCAT_VERSION='${TOMCAT_VERSION}'|g" $DOWNLOAD_DIR/add-auth-ldap.sh sed -i "s|TOMCAT_VERSION=|TOMCAT_VERSION='${TOMCAT_VERSION}'|g" $DOWNLOAD_DIR/add-auth-totp.sh sed -i "s|TOMCAT_VERSION=|TOMCAT_VERSION='${TOMCAT_VERSION}'|g" $DOWNLOAD_DIR/add-fail2ban.sh -# As web links may contain "&" characters, GUAC_SOURCE_LINK is fixed to parse "&" with sed correctly +sed -i "s|CERT_COUNTRY=|CERT_COUNTRY='${CERT_COUNTRY}'|g" $DOWNLOAD_DIR/add-ssl-guac-gaucd.sh +sed -i "s|CERT_STATE=|CERT_STATE='${CERT_STATE}'|g" $DOWNLOAD_DIR/add-ssl-guac-gaucd.sh +sed -i "s|CERT_LOCATION=|CERT_LOCATION='${CERT_LOCATION=}'|g" $DOWNLOAD_DIR/add-ssl-guac-gaucd.sh +sed -i "s|CERT_ORG=|CERT_ORG='${CERT_ORG}'|g" $DOWNLOAD_DIR/add-ssl-guac-gaucd.sh +sed -i "s|CERT_OU=|CERT_OU='${CERT_OU}'|g" $DOWNLOAD_DIR/add-ssl-guac-gaucd.sh +# As dynamic web links may contain "&" characters, GUAC_SOURCE_LINK is fixed to parse "&" with sed correctly FIXED_LINK=$(sed 's/\&/\\&/g' <<< $GUAC_SOURCE_LINK) sed -i "s|GUAC_SOURCE_LINK=|GUAC_SOURCE_LINK='${FIXED_LINK}'|g" $DOWNLOAD_DIR/add-auth-duo.sh sed -i "s|GUAC_SOURCE_LINK=|GUAC_SOURCE_LINK='${FIXED_LINK}'|g" $DOWNLOAD_DIR/add-auth-ldap.sh @@ -479,7 +569,7 @@ sed -i "s|GUAC_SOURCE_LINK=|GUAC_SOURCE_LINK='${FIXED_LINK}'|g" $DOWNLOAD_DIR/ad # Pass the relevant variable selections to child install scripts below # (This is a more robust method than export, which is unreliable in this instance) COLOUR_VAR="GREY=$GREY DGREY=$DGREY GREYB=$GREYB RED=$RED LRED=$LRED GREEN=$GREEN LGREEN=$LGREEN YELLOW=$YELLOW LYELLOW=$LYELLOW BLUE=$BLUE LBLUE=$LBLUECYAN=$CYAN LCYAN=$LCYAN MAGENTA=$MAGENTA LMAGENTA=$LMAGENTA NC=$NC" -GUAC_VAR="JPEGTURBO=$JPEGTURBO LIBPNG=$LIBPNG GUAC_VERSION=$GUAC_VERSION MYSQLJCON=$MYSQLJCON GUAC_SOURCE_LINK=$GUAC_SOURCE_LINK TOMCAT_VERSION=$TOMCAT_VERSION LOG_LOCATION=$LOG_LOCATION INSTALL_MYSQL=$INSTALL_MYSQL SECURE_MYSQL=$SECURE_MYSQL MYSQL_HOST=$MYSQL_HOST MYSQL_PORT=$MYSQL_PORT GUAC_DB=$GUAC_DB GUAC_USER=$GUAC_USER GUAC_PWD=$GUAC_PWD MYSQL_ROOT_PWD=$MYSQL_ROOT_PWD INSTALL_TOTP=$INSTALL_TOTP INSTALL_DUO=$INSTALL_DUO INSTALL_LDAP=$INSTALL_LDAP EMAIL_DOMAIN=$EMAIL_DOMAIN" +GUAC_VAR="JPEGTURBO=$JPEGTURBO LIBPNG=$LIBPNG GUAC_VERSION=$GUAC_VERSION MYSQLJCON=$MYSQLJCON GUAC_SOURCE_LINK=$GUAC_SOURCE_LINK TOMCAT_VERSION=$TOMCAT_VERSION LOG_LOCATION=$LOG_LOCATION INSTALL_MYSQL=$INSTALL_MYSQL SECURE_MYSQL=$SECURE_MYSQL MYSQL_HOST=$MYSQL_HOST MYSQL_PORT=$MYSQL_PORT GUAC_DB=$GUAC_DB GUAC_USER=$GUAC_USER GUAC_PWD=$GUAC_PWD MYSQL_ROOT_PWD=$MYSQL_ROOT_PWD INSTALL_TOTP=$INSTALL_TOTP INSTALL_DUO=$INSTALL_DUO INSTALL_LDAP=$INSTALL_LDAP BACKUP_EMAIL=$BACKUP_EMAIL" NGINX_VAR="TOMCAT_VERSION=$TOMCAT_VERSION LOG_LOCATION=$LOG_LOCATION GUAC_URL=$GUAC_URL PROXY_SITE=$PROXY_SITE" SELF_SIGN_VAR="DOWNLOAD_DIR=$DOWNLOAD_DIR TMP_DIR=$TMP_DIR TOMCAT_VERSION=$TOMCAT_VERSION LOG_LOCATION=$LOG_LOCATION GUAC_URL=$GUAC_URL PROXY_SITE=$PROXY_SITE CERT_COUNTRY=$CERT_COUNTRY CERT_STATE=$CERT_STATE CERT_LOCATION=$CERT_LOCATION CERT_ORG=$CERT_ORG CERT_OU=$CERT_OU" LE_VAR="DOWNLOAD_DIR=$DOWNLOAD_DIR TOMCAT_VERSION=$TOMCAT_VERSION LOG_LOCATION=$LOG_LOCATION PROXY_SITE=$PROXY_SITE GUAC_URL=$GUAC_URL LE_DNS_NAME=$LE_DNS_NAME LE_EMAIL=$LE_EMAIL" @@ -490,23 +580,23 @@ if [ $? -ne 0 ]; then echo -e "${RED}2-install-guacamole.sh FAILED. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 else - echo -e "${LGREEN}Guacamole installation complete\n- Visit: http://${PROXY_SITE}:8080/guacamole\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***.${GREY}" + echo -e "${LGREEN}Guacamole installation complete\n- Visit: http://${PROXY_SITE}:8080/guacamole\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***${GREY}" fi -# Duo Settings reminder that if due is slected you cant login to Guacamole at all until this extension is fully configured +# Duo Settings reminder - If Duo is selected you can't login to Guacamole at all until this extension is fully configured if [ $INSTALL_DUO == "true" ]; then echo -e "${YELLOW}Reminder: Duo requires extra account specific config before you can log in to Guacamole." echo -e "See https://guacamole.apache.org/doc/${GUAC_VERSION}/gug/duo-auth.html" fi # Add a Guacamole database backup (mon-fri 12:00am) into cron -crontab -l > cron_1 > /dev/null 2>&1 +crontab -l > cron_1 # Remove existing entry to allow multiple runs sed -i '/# backup guacamole/d' cron_1 # Create the job echo "0 0 * * 1-5 ${DOWNLOAD_DIR}/backup-guac.sh # backup guacamole" >> cron_1 # Overwrite the cron settings and cleanup -crontab cron_1 > /dev/null 2>&1 +crontab cron_1 rm cron_1 @@ -516,30 +606,31 @@ rm cron_1 ### Install Nginx reverse proxy front end to Guacamole if option is selected if [ "${INSTALL_NGINX}" = true ]; then - sudo $NGINX_VAR $COLOUR_VAR ./3-install-nginx.sh | tee -a ${LOG_LOCATION} - echo -e "${LGREEN}Nginx installation complete\n- Site changed to : http://${PROXY_SITE}\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***.${GREY}" + sudo $NGINX_VAR $COLOUR_VAR ./3-install-nginx.sh + echo -e "${LGREEN}Nginx installation complete\n- Site changed to : http://${PROXY_SITE}\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***${GREY}" fi ### Apply self signed SSL certificates to Nginx reverse proxy if option is selected -if [[ "${INSTALL_NGINX}" = true ]] && [[ "${SELF_SIGNED}" = true ]]; then - sudo -E $SELF_SIGN_VAR $COLOUR_VAR ./4a-install-ssl-self-signed-nginx.sh ${PROXY_SITE} ${CERT_DAYS} | tee -a ${LOG_LOCATION} -echo -e "${LGREEN}Self signed certificates successfully created and configured for Nginx \n- Site changed to : ${LYELLOW}https:${LGREEN}//${PROXY_SITE}\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***.${GREY}" +if [[ "${INSTALL_NGINX}" = true ]] && [[ "${SELF_SIGN}" = true ]]; then + sudo -E $SELF_SIGN_VAR $COLOUR_VAR ./4a-install-ssl-self-signed-nginx.sh ${PROXY_SITE} ${CERT_DAYS} +echo -e "${LGREEN}Self signed certificates successfully created and configured for Nginx \n- Site changed to : ${LYELLOW}https:${LGREEN}//${PROXY_SITE}\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***${GREY}" fi ### Apply Let's Encrypt SSL certificates to Nginx reverse proxy if option is selected -if [[ "${INSTALL_NGINX}" = true ]] && [[ "${INSTALL_LETS_ENCRYPT}" = true ]]; then - sudo -E $LE_VAR $COLOUR_VAR ./4b-install-ssl-letsencrypt-nginx.sh | tee -a ${LOG_LOCATION} -echo -e "${LGREEN}Let's Encrypt SSL successfully configured for Nginx \n- Site changed to : ${LYELLOW}https:${LGREEN}//${LE_DNS_NAME}\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***.${GREY}" +if [[ "${INSTALL_NGINX}" = true ]] && [[ "${LETS_ENCRYPT}" = true ]]; then + sudo -E $LE_VAR $COLOUR_VAR ./4b-install-ssl-letsencrypt-nginx.sh +echo -e "${LGREEN}Let's Encrypt SSL successfully configured for Nginx \n- Site changed to : ${LYELLOW}https:${LGREEN}//${LE_DNS_NAME}\n- Default login (user/pass): guacadmin/guacadmin\n${LYELLOW}***Be sure to change the password***${GREY}" fi # Final tidy up +echo +echo -e "${LGREEN}1-setup.sh was moved to ${USER_HOME_DIR}/guacamole." mv $USER_HOME_DIR/1-setup.sh $DOWNLOAD_DIR sudo rm -R $TMP_DIR - # Done echo printf "${LGREEN}Guacamole ${GUAC_VERSION} install complete! \n${NC}" diff --git a/2-install-guacamole.sh b/2-install-guacamole.sh index 8cca399..d0ab8b7 100644 --- a/2-install-guacamole.sh +++ b/2-install-guacamole.sh @@ -8,8 +8,36 @@ # pls see https://github.com/MysticRyuujin/guac-install for more ####################################################################################################################### +# Prepare text output colours +GREY='\033[0;37m' +DGREY='\033[0;90m' +GREYB='\033[1;37m' +RED='\033[0;31m' +LRED='\033[0;91m' +GREEN='\033[0;32m' +LGREEN='\033[0;92m' +YELLOW='\033[0;33m' +LYELLOW='\033[0;93m' +BLUE='\033[0;34m' +LBLUE='\033[0;94m' +CYAN='\033[0;36m' +LCYAN='\033[0;96m' +MAGENTA='\033[0;35m' +LMAGENTA='\033[0;95m' +NC='\033[0m' #No Colour + clear +#Script branding header +echo +echo -e "${GREYB}Itiligent Virtual Desktop Appliance Setup." +echo -e " ${LGREEN}Powered by Guacamole" + +echo +echo +echo -e "Beginning Guacamole setup...${GREY}" +echo + # Pre-seed MySQL install values if [ "${INSTALL_MYSQL}" = true ]; then debconf-set-selections <<< "mysql-server mysql-server/root_password password ${MYSQL_ROOT_PWD}" @@ -26,11 +54,10 @@ if [ "${INSTALL_MYSQL}" = true ]; then fi # Don't do annoying prompts during apt installs -echo echo -e "${GREY}Updating base Linux OS..." -export DEBIAN_FRONTEND=noninteractive &>> ${LOG_LOCATION} -sudo apt-get update &>> ${LOG_LOCATION} -sudo apt-get upgrade -y &>> ${LOG_LOCATION} +export DEBIAN_FRONTEND=noninteractive +sudo apt-get update -qq &>> ${LOG_LOCATION} +sudo apt-get upgrade -qq -y &>> ${LOG_LOCATION} if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 @@ -41,10 +68,9 @@ fi # Install Guacamole build dependencies. echo echo -e "${GREY}Installing dependencies required for building Guacamole, this might take a few minutes..." -apt-get -y install ${JPEGTURBO} ${LIBPNG} ufw htop pwgen wget crudini build-essential libcairo2-dev libtool-bin uuid-dev libavcodec-dev libavformat-dev libavutil-dev \ +apt-get -qq -y install ${JPEGTURBO} ${LIBPNG} ufw htop pwgen wget crudini build-essential libcairo2-dev libtool-bin uuid-dev libavcodec-dev libavformat-dev libavutil-dev \ libswscale-dev freerdp2-dev libpango1.0-dev libssh2-1-dev libtelnet-dev libvncserver-dev libwebsockets-dev libpulse-dev libssl-dev \ -libvorbis-dev libwebp-dev ghostscript \ -${MYSQL} ${TOMCAT_VERSION} &>> ${LOG_LOCATION} +libvorbis-dev libwebp-dev ghostscript ${MYSQL} ${TOMCAT_VERSION} &>> ${LOG_LOCATION} if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 @@ -52,20 +78,17 @@ if [ $? -ne 0 ]; then echo -e "${LGREEN}OK${GREY}" fi -# Setup email relay +# Install Postfix with default settings for smtp email relay echo -echo -e "${GREY}Setting up SMTP for backup alerts (requires SMTP relay be permitted from this server's IP address)..." -echo "postfix postfix/mailname string ${EMAIL_DOMAIN} | debconf-set-selections" &>> ${LOG_LOCATION} -DEBIAN_FRONTEND="noninteractive" apt-get install postfix -y &>> ${LOG_LOCATION} -apt-get install mailutils -y &>> ${LOG_LOCATION} -sed -i 's/inet_interfaces = all/inet_interfaces = loopback-only/g' /etc/postfix/main.cf &>> ${LOG_LOCATION} -service postfix restart &>> ${LOG_LOCATION} +echo -e "${GREY}Installing SMTP email for backup email notifications, for SMTP realy with Office365, see separate configuration script..." +DEBIAN_FRONTEND="noninteractive" apt-get install postfix mailutils -qq -y &>> ${LOG_LOCATION} if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 else echo -e "${LGREEN}OK${GREY}" fi +service postfix restart # Download Guacamole Server echo @@ -150,7 +173,6 @@ if [ $? -ne 0 ]; then fi echo -e "${LGREEN}Downloaded mysql-connector-java-${MYSQLJCON}.tar.gz${GREY}" -echo echo -e "${LGREEN}Source download complete.${GREY}" # Option to pause script here as we might want to make final tweaks to source code just before compiling @@ -181,7 +203,7 @@ echo -e "${GREY}Compiling Guacamole-Server from source with with GCC $( gcc --ve export CFLAGS="-Wno-error" # Configure Guacamole Server source -./configure --with-systemd-dir=/etc/systemd/system &>> ${LOG_LOCATION} +./configure --with-systemd-dir=/etc/systemd/system &>> ${LOG_LOCATION} if [ $? -ne 0 ]; then echo "Failed to configure guacamole-server" echo "Trying again with --enable-allow-freerdp-snapshots" @@ -227,7 +249,13 @@ ln -sf /etc/guacamole/guacamole.war /var/lib/${TOMCAT_VERSION}/webapps/ # Move MySQL connector/j files echo -e "${GREY}Moving mysql-connector-java-${MYSQLJCON}.jar (/etc/guacamole/lib/mysql-connector-java.jar)..." mv -f mysql-connector-java-${MYSQLJCON}/mysql-connector-java-${MYSQLJCON}.jar /etc/guacamole/lib/mysql-connector-java.jar -echo +if [ $? -ne 0 ]; then + echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 + exit 1 + else + echo -e "${LGREEN}OK${GREY}" + echo +fi # Move TOTP files if [ "${INSTALL_TOTP}" = true ]; then @@ -467,7 +495,6 @@ if [ $? -ne 0 ]; then exit 1 else echo -e "${LGREEN}OK${GREY}" - echo fi # Done diff --git a/3-install-nginx.sh b/3-install-nginx.sh index 9954d79..ebd73da 100644 --- a/3-install-nginx.sh +++ b/3-install-nginx.sh @@ -7,11 +7,35 @@ # August 2023 ####################################################################################################################### +# Prepare text output colours +GREY='\033[0;37m' +DGREY='\033[0;90m' +GREYB='\033[1;37m' +RED='\033[0;31m' +LRED='\033[0;91m' +GREEN='\033[0;32m' +LGREEN='\033[0;92m' +YELLOW='\033[0;33m' +LYELLOW='\033[0;93m' +BLUE='\033[0;34m' +LBLUE='\033[0;94m' +CYAN='\033[0;36m' +LCYAN='\033[0;96m' +MAGENTA='\033[0;35m' +LMAGENTA='\033[0;95m' +NC='\033[0m' #No Colour + +echo +echo +echo -e "${LGREEN}Installing Nginx...${DGREY}" +echo + # Install Nginx -sudo apt-get install nginx -y &>> ${LOG_LOCATION} +sudo apt-get install nginx -qq -y &>> ${LOG_LOCATION} +echo -e "${GREY}Configuring Nginx as a reverse proxy for Guacamole's Apache Tomcat front end...${DGREY}" # Configure /etc/nginx/sites-available/(local dns site name) -cat >/etc/nginx/sites-available/$PROXY_SITE <&2 exit 1 @@ -46,8 +67,9 @@ ln -s /etc/nginx/sites-available/$PROXY_SITE /etc/nginx/sites-enabled/ unlink /etc/nginx/sites-enabled/default # Do mandatory Nginx tweaks for logging actual client IPs through a proxy IP of 127.0.0.1 - DO NOT CHANGE COMMAND FORMATING! +echo -e "${GREY}Configuring Apache Tomcat valve for pass through of client IPs to Guacamole logs...${GREY}" sudo sed -i '/pattern="%h %l %u %t "%r" %s %b"/a \ \n ' /etc/$TOMCAT_VERSION/server.xml -echo -e "${GREY}Configuring Apache Tomcat's internal proxy valve to support proxy client IP4 & IPv6 address passthough for correct logging and ACL support...${GREY}" + if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 @@ -85,13 +107,12 @@ fi # Update general ufw rules so force traffic via reverse proxy. Only Nginx and SSH will be available over the network. echo -e "${GREY}Updating firewall rules to allow only SSH and tcp 80/443..." -sudo ufw default allow outgoing &>> ${LOG_LOCATION} -sudo ufw default deny incoming &>> ${LOG_LOCATION} -sudo ufw delete allow 8080/tcp &>> ${LOG_LOCATION} -sudo ufw allow OpenSSH &>> ${LOG_LOCATION} -sudo ufw allow 80/tcp &>> ${LOG_LOCATION} -sudo ufw allow 443/tcp &>> ${LOG_LOCATION} -echo "y" | sudo ufw enable &>> ${LOG_LOCATION} +sudo ufw default allow outgoing > /dev/null 2>&1 +sudo ufw default deny incoming > /dev/null 2>&1 +sudo ufw allow OpenSSH > /dev/null 2>&1 +sudo ufw allow 80/tcp > /dev/null 2>&1 +sudo ufw allow 443/tcp > /dev/null 2>&1 +echo "y" | sudo ufw enable > /dev/null 2>&1 if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 @@ -102,15 +123,14 @@ fi # Reload everything echo -e "${GREY}Restaring Guacamole & Ngnix..." -sudo systemctl restart $TOMCAT_VERSION &>> ${LOG_LOCATION} -sudo systemctl restart guacd &>> ${LOG_LOCATION} -sudo systemctl restart nginx &>> ${LOG_LOCATION} +sudo systemctl restart $TOMCAT_VERSION +sudo systemctl restart guacd +sudo systemctl restart nginx if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 else echo -e "${LGREEN}OK${GREY}" - echo fi # Done diff --git a/4a-install-ssl-self-signed-nginx.sh b/4a-install-ssl-self-signed-nginx.sh index 4a55c3f..da93709 100644 --- a/4a-install-ssl-self-signed-nginx.sh +++ b/4a-install-ssl-self-signed-nginx.sh @@ -11,12 +11,34 @@ # to provide certifacate outputs correctly. Runing just as sudo will save certs to sudo's home path # sudo -E ./4a-install-ssl-self-signed-nginx.sh [your-dns-name.local] [3650] +# Prepare text output colours +GREY='\033[0;37m' +DGREY='\033[0;90m' +GREYB='\033[1;37m' +RED='\033[0;31m' +LRED='\033[0;91m' +GREEN='\033[0;32m' +LGREEN='\033[0;92m' +YELLOW='\033[0;33m' +LYELLOW='\033[0;93m' +BLUE='\033[0;34m' +LBLUE='\033[0;94m' +CYAN='\033[0;36m' +LCYAN='\033[0;96m' +MAGENTA='\033[0;35m' +LMAGENTA='\033[0;95m' +NC='\033[0m' #No Colour + +echo +echo +echo -e "${LGREEN}Setting up self signed SSL certificates for Nginx...${GREY}" +echo + # Hack to assist with displaying "$" symbols and " ' quotes in a (cut/pasteable) bash screen output format for Nginx configs SHOWASTEXT1='$mypwd' SHOWASTEXT2='"Cert:\LocalMachine\Root"' # Discover all IPv4 interfaces addresses to bind to new SSL certficates -echo echo -e "${GREY}Discovering the default route interface and DNS names to bind with the new SSL certificate..." # Dump interface info and copy this output to a temp file DUMP_IPS=$(ip -o addr show up primary scope global | while read -r num dev fam addr rest; do echo ${addr%/*}; done) @@ -38,14 +60,11 @@ if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 else - echo -e "${GREEN}OK${GREY}" + echo -e "${LGREEN}OK${GREY}" echo fi -echo -echo -e "${GREY}New self signed SSL certificate attributes are shown below...${GREY}" -echo -e "${DGREY}" - +echo -e "${GREY}New self signed SSL certificate attributes are shown below...${DGREY}" # Display the new SSL cert parameters. Prompt for change if required cat <&2 + exit 1 + else + echo -e "${LGREEN}OK${GREY}" + echo +fi + # Place SSL Certificate within defined path sudo cp $SSLNAME.key $DIR_SSL_KEY/$SSLNAME.key sudo cp $SSLNAME.crt $DIR_SSL_CERT/$SSLNAME.crt # Create a PFX formatted key for easier import to Windows hosts and change permissions to enable copying elsewhere + echo -e "${GREY}Creating client certificates for Windows & Linux...${GREY}" sudo openssl pkcs12 -export -out $SSLNAME.pfx -inkey $SSLNAME.key -in $SSLNAME.crt -password pass:1234 sudo chmod 0774 $SSLNAME.pfx - echo -e "${GREY}Creating a selection of self signed certificates for Nginx and Windows/Linux browser clients...${GREY}" if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 else - echo -e "${GREEN}OK${GREY}" + echo -e "${LGREEN}OK${GREY}" echo fi @@ -125,12 +152,14 @@ if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 else - echo -e "${GREEN}OK${GREY}" + echo -e "${LGREEN}OK${GREY}" echo fi # Update Nginx config to accept the new certificates -cat > /etc/nginx/sites-available/$PROXY_SITE < /dev/null +echo -e "${GREY}Configuring Nginx proxy to use self signed SSL certificates and setting up automatic HTTP to HTTPS redirect...${DGREY}" +#cat > /etc/nginx/sites-available/$PROXY_SITE < /dev/null +cat <&2 exit 1 else - echo -e "${GREEN}OK${GREY}" + echo -e "${LGREEN}OK${GREY}" echo fi + printf "${GREY}+------------------------------------------------------------------------------------------------------------- -${GREEN}+ WINDOWS CLIENT SELF SIGNED SSL BROWSER CONFIG - SAVE THIS BEFORE CONTINUING!${GREY} +${LGREEN}+ WINDOWS CLIENT SELF SIGNED SSL BROWSER CONFIG - SAVE THIS BEFORE CONTINUING!${GREY} + -+ 1. In ${DOWNLOAD_DIR} is a Windows friendly version of the new certificate ${LYELLOW}$SSLNAME.pfx${GREY} ++ 1. In ${DOWNLOAD_DIR} is a new Windows friendly version of the new certificate ${LYELLOW}$SSLNAME.pfx${GREY} + 2. Copy this .pfx file to a location accessible by Windows. -+ 3. Import the PFX file into your Windows client with the below Powershell commands (as administrator): ++ 3. Import the PFX file into your Windows client with the below Powershell commands (as Administrator): \n" echo -e "${SHOWASTEXT1} = ConvertTo-SecureString -String "1234" -Force -AsPlainText" echo -e "Import-pfxCertificate -FilePath $SSLNAME.pfx -Password "${SHOWASTEXT1}" -CertStoreLocation "${SHOWASTEXT2}"" echo -e "(Clear your browser cache and restart your browser to test.)" printf "${GREY}+------------------------------------------------------------------------------------------------------------- -${GREEN}+ LINUX CLIENT SELF SIGNED SSL BROWSER CONFIG - SAVE THIS BEFORE CONTINUING!${GREY} +${LGREEN}+ LINUX CLIENT SELF SIGNED SSL BROWSER CONFIG - SAVE THIS BEFORE CONTINUING!${GREY} + -+ 1. In In ${DOWNLOAD_DIR} is also the Linux native OpenSSL certificate ${LYELLOW}$SSLNAME.crt${GREY} ++ 1. In ${DOWNLOAD_DIR} is a new Linux native OpenSSL certificate ${LYELLOW}$SSLNAME.crt${GREY} + 2. Copy this file to a location accessible by Linux. + 3. Import the CRT file into your Linux client certificate store with the below command (as sudo): \n" @@ -212,7 +240,6 @@ if [ $? -ne 0 ]; then exit 1 else echo -e "${LGREEN}OK${GREY}" - echo fi # Done diff --git a/4b-install-ssl-letsencrypt-nginx.sh b/4b-install-ssl-letsencrypt-nginx.sh index 318b74a..a8b5bd3 100644 --- a/4b-install-ssl-letsencrypt-nginx.sh +++ b/4b-install-ssl-letsencrypt-nginx.sh @@ -7,61 +7,32 @@ # April 2023 ####################################################################################################################### +# Prepare text output colours GREY='\033[0;37m' +DGREY='\033[0;90m' +GREYB='\033[1;37m' RED='\033[0;31m' +LRED='\033[0;91m' +GREEN='\033[0;32m' LGREEN='\033[0;92m' +YELLOW='\033[0;33m' +LYELLOW='\033[0;93m' +BLUE='\033[0;34m' +LBLUE='\033[0;94m' +CYAN='\033[0;36m' +LCYAN='\033[0;96m' +MAGENTA='\033[0;35m' +LMAGENTA='\033[0;95m' NC='\033[0m' #No Colour -# Announce which script you're running -echo -e "${GREY}" -echo -e "Let's Encrypt SSL configuration for Nginx.." - -############################################################################ -# If running this script standalone un-comment entire below section as we need -# the correct $PROXY_SITE, LE_DNS_NAME and LE_EMAIL values to reconfigure Nginx - -#TOMCAT_VERSION="tomcat9" -#LOG_LOCATION=$(eval echo ~${SUDO_USER})/lets-encrypt-inst.log -#DOWNLOAD_DIR=$(eval echo ~${SUDO_USER}) -#GUAC_URL=http://localhost:8080/guacamole/ -#for file in "/etc/nginx/sites-enabled"/* -#do -#PROXY_SITE="${file##*/}" -#done -#echo -#echo -e "${GREY}Discovering exising proxy sites to configure with SSL...${GREY}" -#if [ $? -ne 0 ]; then -# echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 -# exit 1 -# else -# echo -e "${LGREEN}OK${GREY}" -#fi - -# Get domain name for new Let's encrypt certificate -#while true -#do -#echo -e "${LGREEN}" -#read -p "Enter the public FQDN for your proxy site: " LE_DNS_NAME -#echo -# [ "${LE_DNS_NAME}" != "" ] && break -#done - -# Get admin email for Let's encrypt certificate notifications -#while true -#do -#echo -e "${LGREEN}" -#read -p "Enter the email address for Let's Encrypt notifications : " LE_EMAIL -#echo -# [ "${LE_EMAIL}" != "" ] && break -#done - -#echo -e "${GREY}" - -############################################################################ +echo +echo +echo -e "${LGREEN}Installing Let's Encrypt SSL configuration for Nginx...${GREY}" +echo # Install nginx -apt-get update -apt-get install nginx certbot python3-certbot-nginx -y &>> ${LOG_LOCATION} +apt-get update -qq &>> ${LOG_LOCATION} +apt-get install nginx certbot python3-certbot-nginx -qq -y &>> ${LOG_LOCATION} # Backup the current Nginx config cp /etc/nginx/sites-enabled/${PROXY_SITE} $DOWNLOAD_DIR/${PROXY_SITE}-nginx.bak @@ -76,6 +47,7 @@ else fi # Configure Nginx to accept the new certificates +echo -e "${GREY}Configuring Nginx proxy for Let's Encrypt SSL and setting up automatic HTTP redirect...${GREY}" cat > /etc/nginx/sites-available/$PROXY_SITE <&2 exit 1 @@ -110,7 +80,7 @@ systemctl restart nginx # Run certbot to create and associate certificates with currenly public IP (must have tcp 80 and 443 open to work) certbot --nginx -n -d $LE_DNS_NAME --email $LE_EMAIL --agree-tos --redirect --hsts echo -e -echo -e "${GREY}Let's Encrypt successfully installed. Check for errors above (DNS & firewall are usual culprits).${GREY}" +echo -e "${GREY}Let's Encrypt successfully installed, but check for any errors above (DNS & firewall are the usual culprits).${GREY}" if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 exit 1 @@ -123,7 +93,7 @@ fi # If are any due to expire within a 30 day window, Certbot will attempt to renew automatically renew. echo -e "${GREY}Scheduling automatic certificate renewals for certificates with < 30 days till expiry.)${GREY}" #Dump out the current crontab -crontab -l > cron_1 &>> ${LOG_LOCATION} +crontab -l > cron_1 # Remove any previosly added certbot renewal entries sed -i '/# certbot renew/d' cron_1 # Randomly choose a daily update schedule and append this to the cron schedule @@ -131,7 +101,7 @@ HOUR=$(shuf -i 0-23 -n 1) MINUTE=$(shuf -i 0-59 -n 1) echo "${MINUTE} ${HOUR} * * * /usr/bin/certbot renew --quiet --pre-hook 'service nginx stop' --post-hook 'service nginx start'" >> cron_1 # Overwrite old cron settings and cleanup -crontab cron_1 &>> ${LOG_LOCATION} +crontab cron_1 rm cron_1 if [ $? -ne 0 ]; then echo -e "${RED}Failed. See ${LOG_LOCATION}${GREY}" 1>&2 @@ -151,7 +121,6 @@ if [ $? -ne 0 ]; then exit 1 else echo -e "${LGREEN}OK${GREY}" - echo fi # Done diff --git a/README.md b/README.md index 7ef6b89..1822ecf 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,62 @@ -# Guacamole 1.5.0 RDP jump server appliance with MFA, Active Directory integration & Nginx SSL reverse proxy +# Guacamole 1.5.1 Virtual Desktop/Jump Server appliance with MFA, Active Directory integration & Nginx SSL reverse proxy ## Automatic build, install & config script: wget https://raw.githubusercontent.com/itiligent/Guacamole-Setup/main/1-setup.sh && chmod +x 1-setup.sh && ./1-setup.sh - ## Prerequisites: - Ubuntu / Debian / Raspian + Recent flavours of Ubuntu / Debian / Raspian Min 8GB RAM, 40GB HDD Public or private DNS entries matching the default physical interface IP address. (needed for SSL) Incoming access on tcp 22, 80 & 443 - -### All install variables can be set from the first setup script. i.e. Guacamole, Tomcat & MySQL connector versions etc. Follow on screen prompts to install Guacamole, Nginx & SSL. - -### Scripted setup options are: +### Setup menu options are: ### 1. Install default Guacamole with either a local MySQL database or with a remote MySQL instance + sub-options: + a. Add MySQL mysql_secure_installation settings (to a local or remote MySQL instance) + b. Add Guacamole MFA and Auth extensions - DUO, TOTP, LDAP. (Simultaneous TOTP & DUO not possible) - a. Add Guacamole MFA and Auth extensions (DUO, TOTP, LDAP) - b. Add MySQL mysql_secure_installation settings ### 2. Optionally add a reverse proxy front end to Guacamole of either: - a) None: Skip Nginx and keep the default Guacamole front end e.g. http://hostname:8080/guacamole - b) Install Nginx with NO SSL (http 80) e.g. http://hostname.local - c) Install Nginx with SELF SIGNED SSL certificates e.g. https://hostname.local - - includes client certificates for Windows & Linux browsers with final SSL client setup instructions. - d) Install Nginx with LET'S ENCRYPT certificates e.g. https://public.site.com - -### 3. After installation, optional hardening scripts are included for : + b) Install Nginx with NO SSL: e.g. http://hostname.local + c) Install Nginx with SELF SIGNED SSL certificates: e.g. https://hostname.local + - Newly created Windows & Linux browser certs $site.crt, $site.key & $site.pfx are saved to $DOWNLOAD_DIR/guac-setup + - Exact custom commands for the import of client certificates is generated on screen and is logged for later reference. + d) Install Nginx with LET'S ENCRYPT certificates: e.g. https://public.site.com + +### 3. After installation, optional hardening scripts can be manually run for : a. Adding a fail2ban lockdown policy for Guacamole - b. Encryption of internal traffic between the Gaucamole client and Guacd deamon with SSL - To do list: Create hardening scripts for Nginx & MFA for shell access) - -### Items downloaded with the setup command above are setup are placed in the $DOWNLOAD_DIR/guacamole-setup dir as follows + b. Encryption of internal traffic between the Gaucamole client and Guacd daemon with SSL + To do list: (Hardening scripts for Nginx & MFA for shell access) + +## Install notes: + +To create an unattended setup, you must first run the link as above, then EXIT the 1-setup.sh script when prompted. +At this point only a download of all scripts has occurred and from there you may edit the "Silent setup options" +section at the start of 1-setup.sh as needed. + +In 1-setup-sh, any variables with an actual setting i.e. Variable="value" will not prompt during interactive setup, +so with the right combination of saved inputs it is fully possible to deploy Guacamole with Nginx and SSL with zero touch! + +Note: If you have edited 1-setup.sh, you must now run the setup script you saved LOCALLY with ./1-setup.sh (DO NOT RUN AS SUDO). +Beware: If you start setup again from the above wget link this will re-download and overwrite any previous customisations. + +There should be no need to customise any other scripts before installation. All optional (manually run) scripts are +dynamically updated with their specific and relevant variables during setup. Essentially, this means that all scripts are built +to work as a set that are specific to your exact and particular install. Editing anything but 1-setup.sh (untill a at least a full install +is completed) is not recommended. + +To keep any adaptations you do make to any of the scripts, simply comment out the relevant wget lines in the "Download github setup" +section at the top of script 1-setup.sh. This willl prevent any subsequent setup re-runs from overwriting your own edited versions. + +This approach of pre-saving of options in the setup script itself has been taken as a more flexible route because there are far too +many potential inputs and combinations of command line arguments that would need to be passed to the setup script at the command line for +a full build, and this would require an impractically long string of setup arguments to type run correctly. + + # Items downloaded with the setup command above are placed in the $DOWNLOAD_DIR/guac-setup directory... 1. 1-setup.sh - the parent install script itself 2. 2-install-guacamole.sh - Guacamole install script (inspired by https://github.com/MysticRyuujin/guac-install) 3. 3-install-nginx.sh - Installs Nginx and auto configures as a front end for Guacamole (optional) @@ -46,8 +67,10 @@ 8. add-auth-totp.sh - Adds the TOTP MFA extension if not selected at install (optional) 9. add-ssl-guac-gaucd.sh - A hardening script to wrap an extra ssl layer between the guacd server and the Guacamole client (optional) 10. add-fail2ban.sh - Adds and configures fail2ban to secure Guacamole against brute force attacks - 11. backup-guacamole.sh - A simple Guacamole backup script - 12. branding.jar - An extension to customise the Guacomole login screen (optional) + 11. add-smtp-relay-o365.sh - Sets up TLS SMTP authenticated relay with O365 (BYO app password) + 12. backup-guacamole.sh - A simple Guacamole backup script + 13. branding.jar - An extension to customise the Guacomole login screen (optional) see: https://github.com/Zer0CoolX/guacamole-customize-loginscreen-extension -Special acknowledgement to MysticRyuujin @ https://github.com/MysticRyuujin/guac-install and Zer0CoolX @ https://github.com/Zer0CoolX/guacamole-customize-loginscreen-extension whos repos were a helpful source of ideas in assembling this project. +Special acknowledgement to MysticRyuujin @ https://github.com/MysticRyuujin/guac-install and +Zer0CoolX @ https://github.com/Zer0CoolX/guacamole-customize-loginscreen-extension whos repos were a helpful source of ideas in assembling this project. diff --git a/add-auth-duo.sh b/add-auth-duo.sh index d6db814..ee82f3d 100644 --- a/add-auth-duo.sh +++ b/add-auth-duo.sh @@ -35,6 +35,7 @@ fi GUAC_VERSION= TOMCAT_VERSION= GUAC_SOURCE_LINK= + echo wget -q --show-progress -O guacamole-auth-duo-${GUAC_VERSION}.tar.gz ${GUAC_SOURCE_LINK}/binary/guacamole-auth-duo-${GUAC_VERSION}.tar.gz tar -xzf guacamole-auth-duo-${GUAC_VERSION}.tar.gz diff --git a/add-auth-ldap.sh b/add-auth-ldap.sh index d6ec619..a8612eb 100644 --- a/add-auth-ldap.sh +++ b/add-auth-ldap.sh @@ -37,6 +37,7 @@ fi GUAC_VERSION= TOMCAT_VERSION= GUAC_SOURCE_LINK= + echo echo -e "${LYELLOW}Have you updated this script to reflect your Active Directory settings?${NC}" diff --git a/add-auth-totp.sh b/add-auth-totp.sh index f92a735..0a6202f 100644 --- a/add-auth-totp.sh +++ b/add-auth-totp.sh @@ -35,6 +35,7 @@ fi GUAC_VERSION= TOMCAT_VERSION= GUAC_SOURCE_LINK= + echo wget -q --show-progress -O guacamole-auth-totp-${GUAC_VERSION}.tar.gz ${GUAC_SOURCE_LINK}/binary/guacamole-auth-totp-${GUAC_VERSION}.tar.gz tar -xzf guacamole-auth-totp-${GUAC_VERSION}.tar.gz diff --git a/add-fail2ban.sh b/add-fail2ban.sh index 20cb31a..d9d4cd1 100644 --- a/add-fail2ban.sh +++ b/add-fail2ban.sh @@ -104,8 +104,8 @@ fi if [ "${FAIL2BAN_BASE}" = true ]; then #Update and install fail2ban (and john for management of config file updates) -sudo apt-get update > /dev/null 2>&1 -sudo apt-get install fail2ban john -y > /dev/null 2>&1 +sudo apt-get update -qq > /dev/null 2>&1 +sudo apt-get install fail2ban john -qq -y > /dev/null 2>&1 # Create the basic jail.local template cat > /tmp/fail2ban.conf <&2 + exit 1 +fi + +echo +echo -e "${LYELLOW}SMTP relay for Office365 setup...${LGREEN}" + +# Install Posfix +echo +echo -e "${GREY}Installing Postfix with non-interactive defaults..." +sudo apt update -qq > /dev/null 2>&1 +DEBIAN_FRONTEND="noninteractive" apt-get install postfix mailutils -qq -y > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo -e "${RED}Postfix install failed. ${GREY}" 1>&2 + exit 1 +else + echo -e "${LGREEN}OK${GREY}" +fi + +# Get the Office365 smtp authentication credentials +echo +echo -e "${LYELLOW}An Office365 account email account is needed for SMTP relay authentication...${LGREEN}" +echo +read -p "Enter O365 SMTP auth enabled email : " SMTP_EMAIL +read -s -p "Enter the SMTP auth account 'app password': " APP_PWD +echo +echo + +# Remove some default Postifx config items that conflict with new entries +sudo sed -i '/relayhost/d' /etc/postfix/main.cf +sudo sed -i '/smtp_tls_security_level=may/d' /etc/postfix/main.cf + +# For simple relay outbound only, limit Postfix to just loopback and IPv4 +sed -i 's/inet_interfaces = all/inet_interfaces = loopback-only/g' /etc/postfix/main.cf +sed -i "s/inet_protocols = all/inet_protocols = ipv4/g" /etc/postfix/main.cf + +echo -e "${GREY}Configuring Postfix for O365 SMTP relay and TLS auth..." +# Add the new Office365 SMTP auth with TLS settings +cat < /dev/null 2>&1 +relayhost = [smtp.office365.com]:587 +smtp_use_tls = yes +smtp_always_send_ehlo = yes +smtp_sasl_auth_enable = yes +smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd +smtp_sasl_security_options = noanonymous +smtp_sasl_tls_security_options = noanonymous +smtp_tls_security_level = encrypt +smtp_generic_maps = hash:/etc/postfix/generic +smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt +EOF +if [ $? -ne 0 ]; then + echo -e "${RED}Postfix restart failed. ${GREY}" 1>&2 + exit 1 +else + echo -e "${LGREEN}OK${GREY}" + echo +fi + +# Setup the password file and postmap +sudo touch /etc/postfix/sasl_passwd +cat < /dev/null 2>&1 +[smtp.office365.com]:587 ${SMTP_EMAIL}:${APP_PWD} +EOF +sudo chown root:root /etc/postfix/sasl_passwd +sudo chmod 0600 /etc/postfix/sasl_passwd +sudo postmap /etc/postfix/sasl_passwd + +# Setup the generic map file +sudo touch /etc/postfix/generic +cat < /dev/null 2>&1 +root@${SERVER} ${SMTP_EMAIL} +${SENDER}@${SERVER} ${SMTP_EMAIL} +@${DOMAIN_SEARCH_SUFFIX} ${SMTP_EMAIL} +EOF +sudo chown root:root /etc/postfix/generic +sudo chmod 0600 /etc/postfix/generic +sudo postmap /etc/postfix/generic + +# Restart and test +echo -e "${GREY}Restarting Postfix..." +sudo service postfix restart +if [ $? -ne 0 ]; then + echo -e "${RED}Postfix restart failed. ${GREY}" 1>&2 + exit 1 +else + echo -e "${LGREEN}OK${GREY}" +fi + +echo +read -p "Enter an email address to test that email relay is working : " TEST_EMAIL +echo "This is a test email" | mail -s "SMTP Auth Relay Is Working is working" ${TEST_EMAIL} -a "FROM:${SMTP_EMAIL}" +echo -e "${LGREEN}Test message sent.." +echo -e ${NC} + diff --git a/add-ssl-guac-gaucd.sh b/add-ssl-guac-gaucd.sh index e7f4d08..f8f4ea3 100644 --- a/add-ssl-guac-gaucd.sh +++ b/add-ssl-guac-gaucd.sh @@ -24,6 +24,12 @@ MAGENTA='\033[0;35m' LMAGENTA='\033[0;95m' NC='\033[0m' #No Colour +CERT_COUNTRY= +CERT_STATE= +CERT_LOCATION= +CERT_ORG= +CERT_OU= + clear if ! [ $( id -u ) = 0 ]; then @@ -43,11 +49,11 @@ prompt = no string_mask = utf8only [req_distinguished_name] -C = AU -ST = Victoria -L = Melbourne -O = Itiligent -OU = I.T. +C = $CERT_COUNTRY +ST = $CERT_STATE +L = $CERT_LOCATION +O = $CERT_ORG +OU = $CERT_OU CN = localhost [v3_req] diff --git a/backup-guac.sh b/backup-guac.sh index 7360392..1d7aaa7 100644 --- a/backup-guac.sh +++ b/backup-guac.sh @@ -34,11 +34,11 @@ GUAC_USER= GUAC_PWD= GUAC_DB= DB_BACKUP_DIR= -ALERT_EMAIL= -BACKUP_RETAIN_DAYS= +BACKUP_EMAIL= +BACKUP_RETENTION= -# Protect disk space and remove backups older than {BACKUP_RETAIN_DAYS} days -find ${DB_BACKUP_DIR} -mtime +${BACKUP_RETAIN_DAYS} -delete +# Protect disk space and remove backups older than {BACKUP_RETENTION} days +find ${DB_BACKUP_DIR} -mtime +${BACKUP_RETENTION} -delete # Backup code mkdir -p ${DB_BACKUP_DIR} @@ -68,8 +68,8 @@ if [ $? -ne 0 ]; then exit 1 else echo -e "${LGREEN}${GUAC_DB} backup was successfully copied to ${DB_BACKUP_DIR}" - #mailx -s "Guacamomle Database Backup Success" ${ALERT_EMAIL} - echo "${GUAC_DB} backup was successfully copied to $DB_BACKUP_DIR}" | mailx -s "Guacamole backup " ${ALERT_EMAIL} + #mailx -s "Guacamomle Database Backup Success" ${BACKUP_EMAIL} + echo "${GUAC_DB} backup was successfully copied to $DB_BACKUP_DIR" | mailx -s "Guacamole backup " ${BACKUP_EMAIL} fi echo -e ${NC} diff --git a/useful-commands.txt b/useful-commands.txt index 07c2573..302c25f 100644 --- a/useful-commands.txt +++ b/useful-commands.txt @@ -4,11 +4,7 @@ https://ourcodeworld.com/articles/read/949/how-to-perform-a-dos-attack-slow-http slowhttptest -c 10000 -H -g -o ./output_file -i 3 -r 500 -t GET -u http://jumpbox.domain.com -x 24 -p 2 - -## UAudit Guacamole Connections and User access.## - -Query current connection profile allocations - +## Audit Guacamole Connections and User access.## mysql -u root -p guacamole_db select @@ -26,14 +22,11 @@ where Quit to exit -## Reset TOTP configuration for a user account -## This is likely not needed in Gucamole 1.40 as the gui provides an option to reset. Kept for reference. - +# Reset TOTP configuration for a user account +#This is likely not needed in Gucamole 1.40 as the gui provides an option to reset. Kept for reference. mysql -u root -p use guacamol_db; - SELECT user_id FROM guacamole_user INNER JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user.entity_id WHERE guacamole_entity.name = 'guacadmin'; - UPDATE guacamole_user_attribute SET attribute_value='false' WHERE attribute_name = 'guac-totp-key-confirmed' and user_id = '1'; quit;