zer0coolx / guacamole-customize-loginscreen-extension Goto Github PK
View Code? Open in Web Editor NEWAn Apache Guacamole extension to use as a template for customizing or branding the login page.
License: GNU General Public License v3.0
An Apache Guacamole extension to use as a template for customizing or branding the login page.
License: GNU General Public License v3.0
I am not able to load the logo. Everything else works tough.
What path is supposed to be in:
background-image: url('app/ext/tempnamespace/images/logo-placeholder.png');
What else can I write instead of "app/ext/tempnamespace"?
are "app", "ext" and "tempnamespace" variables or specific paths?
Running Guacamole 1.3.0 and tomcat9 on Debian 10
For those looking how to brand and theme Guacmole, I've incorporated the favicon settings mentioned in another thread with an additional dark mode template option here:
https://github.com/itiligent/Guacamole-Install
Just follow the dark-theme readme for instructions on generating and testing your own custom Guacamole theme.
Extension works fine for me in Firefox , Opera etc. But MS IE 11 display wrong logo picture.
Solution is to add tags:
background-repeat: no-repeat; background-size: cover;"
into the first section of login-override.css.
Like this:
.login-ui .login-dialog .logo { background-image: url('app/ext/tempnamespace/images/logo-placeholder.png'); width: 9em; -webkit-background-size: 9em auto; background-repeat: no-repeat; background-size: cover; } div.login-ui { background: #666; background-color: #666; } .login-ui .login-dialog { background-color: white; }
Hello,
Just trying to install custom login extension to an updated centos7.7.1908 and guacamole 1.1.0 in
/var/lib/guacamole/extensions/branding.jar
then
semanage fcontext -a -t tomcat_exec_t "/var/lib/guacamole/extensions/branding.jar"
restorecon -v "/var/lib/guacamole/extensions/branding.jar"
and restart guacd and/or reboot
and still the original Template (with cache clear and test severals browsers)
is your extension still okay with 1.1 or I'am missing on step to install ?
UPDATE
Figured it out myself actually. With the following css I was able to change every aspect (that i wanted) of the login page. Feel free to use it, just change the locations and names to yours.
.login-ui .login-dialog .logo {
background-image: url('app/ext/tempnamespace/images/XXXX.png');
width: 9em;
-webkit-background-size: 9em auto;
}
div.login-ui {
background: url('app/ext/tempnamespace/images/XXXX.png');
background-color: #000;
}
.login-ui .login-dialog {
background-color: transparent;
}
.login-ui .login-dialog .version .version-number {
display: none;
}
.login-ui .login-dialog .login.action_login {
background-color: transparent;
}
.login-ui .login-dialog .login-fields input {
display: block;
border: 1px solid rgba(0, 0, 0, 0.25);
-moz-border-radius: 0.2em;
-webkit-border-radius: 0.2em;
-khtml-border-radius: 0.2em;
font-family: Carlito, FreeSans, Helvetica, Arial, sans-serif;
font-size: 0.9em
border-radius: 0.2em;
width: 100%;
margin: 0;
margin-bottom: 0.5em;
padding: 0.5em 0.75em;
max-width: none;
}
.login-ui .login-dialog .buttons input[type="submit"] {
width: 100%;
margin: 0;
background-color: transparent;
opacity: 0.8;
}
.login-ui .login-fields .labeled-field .field-header {
display: block;
position: absolute;
left: 0;
right: 0;
overflow: hidden;
z-index: -1;
margin: 0.5em;
font-size: 0.9em;
color: white;
opacity: 0.8;
}
.login-ui .login-dialog .version .app-name {
font-weight: bold;
text-transform: uppercase;
text-align: center;
font-size: 1.00em;
color: white;
opacity: 0.8;
}
Thanks for this! Makes it easy enough to customize my guac setup. One question or request if you will. Is there a way to make the "login" button easily changeable as well?
Can this be used to add a second login button i.e. "Login with SSO"?
Instead of having the link in the bottom left when utilising the SAML SSO extension.
Good night friend, I wanted to know the following, I downloaded the branding.jar file, edited the login image and downloaded the en.json file and put it like this:
{
"NAME" : "English",
"APP":{
"NAME" : "MultiTI"
}
}
However after restarting tomcat. instead of appearing the name MultiTI, only APP.NAME appears both in the title and below the logo.
I even created a pt.json and pt_BR.json file with the following content:
{
"NAME" : "Português",
"APP":{
"NAME" : "MultiTI"
}
}
However after restarting tomcat. instead of appearing the name MultiTI, only APP.NAME appears both in the title and below the logo.
I even created a pt.json and pt_BR.json file with the following content:
And yet AppAPP.NAME appears on the login screen, even when I remove branding.jar. Would you know what could be the problem?
PS: I'm from Brazil, so the language of my users' browsers is Brazilian Portuguese.
Hello,
What about an option to change the favicon?
Thank you!
Morning Zer0CoolX, first of all thanks for packaging this deployment has worked like a charm to get it up and running. We have grown our install, and wanted to attach a couple servers to a remote SQL server. However, when I run the script and choose not to install MySQL, it fails to restart the service as it is not found. Any recommendations to what I might need to change to overcome this issue?
Hello,
the customize extension works great, but one question is left: how to use small letters instead of capitals? The text provided seems to get completely converted. Any hints?
I tried to run and edit the branding.jar... Still i'm unable to customize it.
Any steps or thing that i can check where i missed out?
Between i already cleared all cache still the same.
Hello,
I tried to install this extension in ubuntu 18.04 and after execute this command:
$ semanage fcontext -a -t tomcat_exec_t "/etc/guacamole/extensions/branding.jar"
Traceback (most recent call last):
File "/usr/sbin/semanage", line 28, in
import seobject
File "/usr/lib/python3/dist-packages/seobject.py", line 1039, in
class portRecords(semanageRecords):
File "/usr/lib/python3/dist-packages/seobject.py", line 1041, in portRecords
valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"])
File "/usr/lib/python3/dist-packages/sepolicy/init.py", line 196, in
return ({
File "/usr/lib/python3/dist-packages/setools/typeattrquery.py", line 65, in results
for attr in self.policy.typeattributes():
AttributeError: 'NoneType' object has no attribute 'typeattributes'
Even restarted guacad and tomcat9, I cannot get the jar I edited.
I tried to coping it to /etc/guacamole/extensions/branding.jar end disable SElinux with no success.
Any idea?
Thanks a lot.
Hi, i adatped you script guac-install for Almalinux 8.4 and it works, i'm not able to use git,
`#!/bin/env bash
#Script to install guacamole RDP html5 gateway into Almalinux 8.4
#The script is working in progress is not all my work, i adapted a existent script to my distro
if ! [ $(id -u) = 0 ]; then echo "This script must be run as sudo or root, try again..."; exit 1; fi
if ! [ $(getenforce) = "Enforcing" ]; then echo "This script requires SELinux to be active and in "Enforcing mode""; exit 1; fi
if ! [ $(uname -m) = "x86_64" ]; then echo "This script will only run on 64 bit versions of RHEL/CentOS"; exit 1; fi
if ! rpm -q --quiet "firewalld"; then echo "This script requires firewalld to be installed on the system"; exit 1; fi
set -E
######################################################################
######################################################################
SCRIPT_BUILD="2021_07_03" # Scripts Date for last modified as "yyyy_mm_dd"
ADM_POC="Local Admin, [email protected]" # Point of contact for the Guac server admin
GUAC_STBL_VER="1.3.0" # Latest stable version of Guac from https://guacamole.apache.org/releases/
MYSQL_CON_VER="8.0.25" # Working stable release of MySQL Connecter J
MAVEN_VER="3.8.1" # Latest stable version of Apache Maven
TOMCAT_VER="tomcat9" # Tomcat Version
GUAC_PORT="4822"
MYSQL_PORT="3306"
JKSTORE_KEY_SIZE_DEF="4096" # Default Java Keystore key-size
LE_KEY_SIZE_DEF="4096" # Default Let's Encrypt key-size
SSL_KEY_SIZE_DEF="4096" # Default Self-signed SSL key-size
MYSQL_PASSWD_DEF="guacamole" # Default MySQL/MariaDB root password
DB_NAME_DEF="guac_db" # Defualt database name
DB_USER_DEF="guac_adm" # Defualt database user name
DB_PASSWD_DEF="guacamole" # Defualt database password
JKS_GUAC_PASSWD_DEF="guacamole" # Default Java Keystore password
JKS_CACERT_PASSWD_DEF="guacamole" # Default CACert Java Keystore password, used with LDAPS
GUACD_USER="guacd" # The user name and group of the user running the guacd service
GUAC_URIPATH_DEF="/" # Default URI for Guacamole
DOMAIN_NAME_DEF="localhost" # Default domain name of server
H_ERR=false # Defualt value of if an error has been triggered, should be false
LIBJPEG_EXCLUDE="exclude=libjpeg-turbo-[0-9],libjpeg-turbo-..9[0-9]-"
DEL_TMP_VAR=true # Default behavior to delete the temp var file used by error handler on completion. Set to false to keep the file to review last values
NAME_SERVERS_DEF="1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001" # OCSP resolver DNS name servers defaults !!Only used if the host does not have name servers in resolv.conf!!
MYSQL_CON_URL="https://dev.mysql.com/get/Downloads/Connector-J/" #Direct URL for download
LIBJPEG_REPO="https://libjpeg-turbo.org/pmwiki/uploads/Downloads/libjpeg-turbo.repo"
LIB_DIR="/var/lib/guacamole/"
GUAC_CONF="guacamole.properties" # Guacamole configuration/properties file
MYSQL_CON="mysql-connector-java-${MYSQL_CON_VER}"
TMP_VAR_FILE="guac_tmp_vars" # Temp file name used to store varaibles for the error handler
Black=tput setaf 0
#${Black}
Red=tput setaf 1
#${Red}
Green=tput setaf 2
#${Green}
Yellow=tput setaf 3
#${Yellow}
Blue=tput setaf 4
#${Blue}
Magenta=tput setaf 5
#${Magenta}
Cyan=tput setaf 6
#${Cyan}
White=tput setaf 7
#${White}
Bold=tput bold
#${Bold}
UndrLn=tput sgr 0 1
#${UndrLn}
Rev=tput smso
#${Rev}
Reset=tput sgr0
#${Reset}
init_vars () {
GUAC_GIT_VER=curl -s https://raw.githubusercontent.com/apache/guacamole-server/master/configure.ac | grep 'AC_INIT([guacamole-server]*' | awk -F'[][]' -v n=2 '{ print $(2*n) }'
PWD=pwd
# Current directory
VAR_FILE="${PWD}/${TMP_VAR_FILE}"
echo "-1" > "${VAR_FILE}" # create file with -1 to set not as background process
if grep -q "CentOS" /etc/redhat-release; then
OS_NAME="CentOS"
elif grep -q "Red Hat Enterprise" /etc/redhat-release; then
OS_NAME="RHEL"
elif grep -q "AlmaLinux release 8.4" /etc/redhat-release; then
OS_NAME="CentOS"
else
echo "Unable to verify OS from /etc/redhat-release as CentOS or RHEL, this script is intended only for those distro's, exiting."
exit 1
fi
OS_NAME_L="$(echo $OS_NAME | tr '[:upper:]' '[:lower:]')" # Set lower case rhel or centos for use in some URLs
MAJOR_VER=cat /etc/redhat-release | grep -oP "[0-9]+" | sed -n 1p
# Return the leftmost digit representing major version
MINOR_VER=cat /etc/redhat-release | grep -oP "[0-9]+" | sed -n 2p
# Returns the middle digit representing minor version
cat /etc/redhat-release | grep -oP "[0-9]+" | sed -n 3p
# Returns the rightmost digits representing release number#Set arch used in some paths
MACHINE_ARCH=uname -m
ARCH="64"
NGINX_URL="https://nginx.org/packages/$OS_NAME_L/$MAJOR_VER/$MACHINE_ARCH/"
}
src_vars () {
if [ $GUAC_SOURCE == "Git" ]; then
GUAC_VER=${GUAC_GIT_VER}
GUAC_URL="git://github.com/apache/"
GUAC_SERVER="guacamole-server.git"
GUAC_CLIENT="guacamole-client.git"
MAVEN_MAJOR_VER=${MAVEN_VER:0:1}
MAVEN_URL="https://www-us.apache.org/dist/maven/maven-${MAVEN_MAJOR_VER}/${MAVEN_VER}/binaries/"
MAVEN_FN="apache-maven-${MAVEN_VER}"
MAVEN_BIN="${MAVEN_FN}-bin.tar.gz"
else # Stable release
GUAC_VER=${GUAC_STBL_VER}
GUAC_URL="https://apache.org/dyn/closer.cgi?action=download&filename=guacamole/${GUAC_VER}/"
GUAC_SERVER="guacamole-server-${GUAC_VER}"
GUAC_CLIENT="guacamole-${GUAC_VER}"
fi
GUAC_JDBC="guacamole-auth-jdbc-${GUAC_VER}"
GUAC_LDAP="guacamole-auth-ldap-${GUAC_VER}"
GUAC_TOTP="guacamole-auth-totp-${GUAC_VER}"
INSTALL_DIR="/usr/local/src/guacamole/${GUAC_VER}/" # Guacamole installation dir
FILENAME="${PWD}/guacamole-${GUAC_VER}_"$(date +"%d-%y-%b")"" # Script generated log filename
logfile="${FILENAME}.log" # Script generated log file full name
fwbkpfile="${FILENAME}.firewall.bkp" # Firewall backup file name
}
######################################################################
######################################################################
src_menu () {
clear
echo -e " ${Reset}${Bold}----====Gucamole Installation Script====----\n ${Reset}Guacamole Remote Desktop Gateway\n"
echo -e " ${Bold}*** Source Menu ***\n"
echo " OS: ${Yellow}${OS_NAME} ${MAJOR_VER}.${MINOR_VER} ${MACHINE_ARCH}${Reset}"
echo -e " ${Bold}Stable Version: ${Yellow}${GUAC_STBL_VER}${Reset} || ${Bold}Git Version: ${Yellow}${GUAC_GIT_VER}${Reset}\n"
while true; do
echo -n "${Green} Pick the desired source to install from (enter 'stable' or 'git', default is 'stable'): ${Yellow}"
read GUAC_SOURCE
case $GUAC_SOURCE in
[Ss]table|"" ) GUAC_SOURCE="Stable"; break;;
[Gg][Ii][Tt] ) GUAC_SOURCE="Git"; break;;
* ) echo "${Green} Please enter 'stable' or 'git' to select source/version (without quotes)";;
esac
done
tput sgr0
}
init_vars
src_menu
src_vars
menu_header () {
tput sgr0
clear
echo -e " ${Reset}${Bold}----====Gucamole Installation Script====----\n ${Reset}Guacamole Remote Desktop Gateway\n"
echo -e " ${Bold}*** ${SUB_MENU_TITLE} ***\n"
echo " OS: ${Yellow}${OS_NAME} ${MAJOR_VER}.${MINOR_VER} ${MACHINE_ARCH}${Reset}"
echo -e " ${Bold}Source/Version: ${Yellow}${GUAC_SOURCE} ${GUAC_VER}${Reset}\n"
}
db_menu () {
SUB_MENU_TITLE="Database and JKS Menu"
menu_header
echo -n "${Green} Enter the Guacamole DB name (default ${DB_NAME_DEF}): ${Yellow}"
read DB_NAME
DB_NAME=${DB_NAME:-${DB_NAME_DEF}}
echo -n "${Green} Enter the Guacamole DB username (default ${DB_USER_DEF}): ${Yellow}"
read DB_USER
DB_USER=${DB_USER:-${DB_USER_DEF}}
echo -n "${Green} Enter the Java KeyStore key-size to use (default ${JKSTORE_KEY_SIZE_DEF}): ${Yellow}"
read JKSTORE_KEY_SIZE
JKSTORE_KEY_SIZE=${JKSTORE_KEY_SIZE:-${JKSTORE_KEY_SIZE_DEF}}
}
pw_menu () {
SUB_MENU_TITLE="Passwords Menu"
menu_header
echo -n "${Green} Enter the root password for MariaDB: ${Yellow}"
read MYSQL_PASSWD
MYSQL_PASSWD=${MYSQL_PASSWD:-${MYSQL_PASSWD_DEF}}
echo -n "${Green} Enter the Guacamole DB password: ${Yellow}"
read DB_PASSWD
DB_PASSWD=${DB_PASSWD:-${DB_PASSWD_DEF}}
echo -n "${Green} Enter the Guacamole Java KeyStore password, must be 6 or more characters: ${Yellow}"
read JKS_GUAC_PASSWD
JKS_GUAC_PASSWD=${JKS_GUAC_PASSWD:-${JKS_GUAC_PASSWD_DEF}}
}
ssl_cert_type_menu () {
SUB_MENU_TITLE="SSL Certificate Type Menu"
menu_header
echo "${Green} What kind of SSL certificate should be used (default 2)?${Yellow}"
PS3="${Green} Enter the number of the desired SSL certificate type: ${Yellow}"
options=("LetsEncrypt" "Self-signed" "None")
select opt in "${options[@]}"
do
case $opt in
"LetsEncrypt") SSL_CERT_TYPE="LetsEncrypt"; le_menu; break;;
"Self-signed"|"") SSL_CERT_TYPE="Self-signed"; ss_menu; break;;
"None")
SSL_CERT_TYPE="None"
OCSP_USE=false
echo -e "\n\n${Red} No SSL certificate selected. This can be configured manually at a later time."
sleep 3
break;;
* ) echo "${Green} ${REPLY} is not a valid option, enter the number representing your desired cert type.";;
esac
done
}
le_menu () {
SUB_MENU_TITLE="LetsEncrypt Menu"
menu_header
echo -n "${Green} Enter a valid e-mail for let's encrypt certificate: ${Yellow}"
read EMAIL_NAME
echo -n "${Green} Enter the Let's Encrypt key-size to use (default ${LE_KEY_SIZE_DEF}): ${Yellow}"
read LE_KEY_SIZE
LE_KEY_SIZE=${LE_KEY_SIZE:-${LE_KEY_SIZE_DEF}}
while true; do
echo -n "${Green} Use OCSP Stapling (default yes): ${Yellow}"
read yn
case $yn in
[Yy]|"" ) OCSP_USE=true; break;;
[Nn] ) OCSP_USE=false; break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
}
ss_menu () {
OCSP_USE=false
SUB_MENU_TITLE="Self-signed SSL Certificate Menu"
menu_header
echo -n "${Green} Enter the Self-Signed SSL key-size to use (default ${SSL_KEY_SIZE_DEF}): ${Yellow}"
read SSL_KEY_SIZE
SSL_KEY_SIZE=${SSL_KEY_SIZE:-${SSL_KEY_SIZE_DEF}}
}
nginx_menu () {
SUB_MENU_TITLE="Nginx Menu"
menu_header
GUAC_LAN_IP_DEF=$(hostname -I | sed 's/ .*//')
echo -n "${Green} Enter the LAN IP of this server (default ${GUAC_LAN_IP_DEF}): ${Yellow}"
read GUAC_LAN_IP
GUAC_LAN_IP=${GUAC_LAN_IP:-${GUAC_LAN_IP_DEF}}
echo -n "${Green} Enter a valid hostname or public domain such as mydomain.com (default ${DOMAIN_NAME_DEF}): ${Yellow}"
read DOMAIN_NAME
DOMAIN_NAME=${DOMAIN_NAME:-${DOMAIN_NAME_DEF}}
echo -n "${Green} Enter the URI path, starting and ending with / for example /guacamole/ (default ${GUAC_URIPATH_DEF}): ${Yellow}"
read GUAC_URIPATH
GUAC_URIPATH=${GUAC_URIPATH:-${GUAC_URIPATH_DEF}}
if [ $SSL_CERT_TYPE != "None" ]; then
while true; do
echo -n "${Green} Use only >= 256-bit SSL ciphers (More secure, less compatible. default: yes)?: ${Yellow}"
read yn
case $yn in
[Yy]|"" ) NGINX_SEC=true; break;;
[Nn] ) NGINX_SEC=false; break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
while true; do
echo -n "${Green} Use Content-Security-Policy [CSP] (More secure, less compatible. default: yes)?: ${Yellow}"
read yn
case $yn in
[Yy]*|"" ) USE_CSP=true; break;;
[Nn]* ) USE_CSP=false; break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
else
NGINX_SEC=false
USE_CSP=false
fi
}
prime_auth_ext_menu () {
SUB_MENU_TITLE="Primary Authentication Extensions Menu"
menu_header
INSTALL_LDAP=false
SECURE_LDAP=false
INSTALL_RADIUS=false
INSTALL_CAS=false
INSTALL_OPENID=false
echo "${Green} What Guacamole extension should be used as the primary user authentication method (default 1)?${Yellow}"
PS3="${Green} Enter the number of the desired authentication method: ${Yellow}"
options=("MariaDB Database" "LDAP(S)")
COLUMNS=1
select opt in "${options[@]}"
do
case $opt in
"MariaDB Database"|"") PRIME_AUTH_TYPE="MariaDB"; break;;
"LDAP(S)") PRIME_AUTH_TYPE="LDAP"; LDAP_ext_menu; break;;
# "RADIUS") PRIME_AUTH_TYPE="RADIUS"; Radius_ext_menu; break;;
# "OpenID") PRIME_AUTH_TYPE="OpenID"; OpenID_ext_menu; break;;
# "CAS") PRIME_AUTH_TYPE="CAS"; CAS_ext_menu; break;;
* ) echo "${Green} ${REPLY} is not a valid option, enter the number representing the desired primary authentication method.";;
esac
done
unset COLUMNS
}
secondary_auth_ext_menu () {
SUB_MENU_TITLE="2FA Extensions Menu"
menu_header
INSTALL_TOTP=false
INSTALL_DUO=false
echo "${Green} What Guacamole extension should be used as the 2FA authentication method (default 1)?${Yellow}"
PS3="${Green} Enter the number of the desired authentication method: ${Yellow}"
options=("None" "TOTP")
COLUMNS=1
select opt in "${options[@]}"
do
case $opt in
"None"|"") TFA_TYPE="None"; break;;
"TOTP") TFA_TYPE="TOTP"; TOTP_ext_menu; break;;
# "DUO") TFA_TYPE="DUO"; Duo_ext_menu; break;;
* ) echo "${Green} ${REPLY} is not a valid option, enter the number representing the desired 2FA method.";;
esac
done
unset COLUMNS
}
LDAP_ext_menu () {
INSTALL_LDAP=true
SUB_MENU_TITLE="LDAP Extension Menu"
menu_header
while true; do
echo -n "${Green} Use LDAPS instead of LDAP (Requires having the cert from the server copied locally, default: no): ${Yellow}"
read SECURE_LDAP
case $SECURE_LDAP in
[Yy]* ) SECURE_LDAP=true; break;;
[Nn]*|"" ) SECURE_LDAP=false; break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
if [ $SECURE_LDAP = true ]; then
echo -ne "\n${Green} Enter the LDAP Port (default 636): ${Yellow}"
read LDAP_PORT
LDAP_PORT=${LDAP_PORT:-636}
# LDAPS Certificate placeholder values
LDAPS_CERT_FN="mycert.cer"
LDAPS_CERT_FULL="xNULLx"
while [ ! -f ${LDAPS_CERT_FULL} ]; do
echo -ne "\n${Green} Enter a valid filename of the .cer certificate file (Ex: mycert.cer): ${Yellow}"
read LDAPS_CERT_FN
LDAPS_CERT_FN=${LDAPS_CERT_FN:-${LDAPS_CERT_FN}}
echo -n "${Green} Enter the full path of the dir containing the .cer certificate file (must end with / Ex: /home/me/): ${Yellow}"
read LDAPS_CERT_DIR
LDAPS_CERT_DIR=${LDAPS_CERT_DIR:-/home/}
LDAPS_CERT_FULL=${LDAPS_CERT_DIR}${LDAPS_CERT_FN}
if [ ! -f ${LDAPS_CERT_FULL} ]; then
echo "${Red} The file/path: ${LDAPS_CERT_FULL} does not exist! Ensure the file is in the directory and try again..."
fi
done
echo -ne "\n${Green} Set the password for the CACert Java Keystore, must be 6 or more characters (default ${JKS_CACERT_PASSWD_DEF}): ${Yellow}"
read JKS_CACERT_PASSWD
JKS_CACERT_PASSWD=${JKS_CACERT_PASSWD:-${JKS_CACERT_PASSWD_DEF}}
else # Use LDAP not LDAPS
echo -ne "\n${Green} Enter the LDAP Port (default 389): ${Yellow}"
read LDAP_PORT
LDAP_PORT=${LDAP_PORT:-389}
fi
echo -ne "\n${Green} Enter the LDAP Server Hostname (use the FQDN, Ex: ldaphost.domain.com): ${Yellow}"
read LDAP_HOSTNAME
LDAP_HOSTNAME=${LDAP_HOSTNAME:-ldaphost.domain.com}
echo -n "${Green} Enter the LDAP User-Base-DN (Ex: dc=domain,dc=com): ${Yellow}"
read LDAP_BASE_DN
LDAP_BASE_DN=${LDAP_BASE_DN:-dc=domain,dc=com}
echo -n "${Green} Enter the LDAP Search-Bind-DN (Ex: cn=user,ou=Admins,dc=domain,dc=com): ${Yellow}"
read LDAP_BIND_DN
LDAP_BIND_DN=${LDAP_BIND_DN:-cn=user,ou=Admins,dc=domain,dc=com}
echo -n "${Green} Enter the LDAP Search-Bind-Password: ${Yellow}"
read LDAP_BIND_PW
LDAP_BIND_PW=${LDAP_BIND_PW:-password}
echo -n "${Green} Enter the LDAP Username-Attribute (default sAMAccountName): ${Yellow}"
read LDAP_UNAME_ATTR
LDAP_UNAME_ATTR=${LDAP_UNAME_ATTR:-sAMAccountName}
LDAP_SEARCH_FILTER_DEF="(objectClass=*)"
echo -n "${Green} Enter a custom LDAP user search filter (default "${LDAP_SEARCH_FILTER_DEF}"): ${Yellow}"
read LDAP_SEARCH_FILTER
LDAP_SEARCH_FILTER=${LDAP_SEARCH_FILTER:-${LDAP_SEARCH_FILTER_DEF}}
}
TOTP_ext_menu () {
INSTALL_TOTP=true
SUB_MENU_TITLE="TOTP Extension Menu"
menu_header
echo -n "${Green} Enter the TOTP issuer (default Apache Guacamole): ${Yellow}"
read TOTP_ISSUER
TOTP_ISSUER=${TOTP_ISSUER:-Apache Guacamole}
echo -n "${Green} Enter the number of digits to use for TOTP (default 6): ${Yellow}"
read TOTP_DIGITS
TOTP_DIGITS=${TOTP_DIGITS:-6}
echo -n "${Green} Enter the TOTP period in seconds (default 30): ${Yellow}"
read TOTP_PER
TOTP_PER=${TOTP_PER:-30}
echo -n "${Green} Enter the TOTP mode (default sha1): ${Yellow}"
read TOTP_MODE
TOTP_MODE=${TOTP_MODE:-sha1}
}
Duo_ext_menu () {
INSTALL_DUO=false
SUB_MENU_TITLE="DUO Extension Menu"
menu_header
echo "${Red} Duo extension not currently available via this script."
sleep 3
}
Radius_ext_menu () {
INSTALL_RADIUS=false
SUB_MENU_TITLE="RADIUS Extension Menu"
menu_header
echo "${Red} RADIUS extension not currently available via this script."
sleep 3
}
CAS_ext_menu () {
INSTALL_CAS=false
SUB_MENU_TITLE="CAS Extension Menu"
menu_header
echo "${Red} CAS extension not currently available via this script."
sleep 3
}
OpenID_ext_menu () {
INSTALL_OPENID=false
SUB_MENU_TITLE="OpenID Extension Menu"
menu_header
echo "${Red} OpenID extension not currently available via this script."
sleep 3
}
cust_ext_menu () {
SUB_MENU_TITLE="Custom Extension Menu"
menu_header
while true; do
echo -n "${Green} Would you like to install a custom Guacamole extensions from a local file (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* )
INSTALL_CUST_EXT=true
# Set placeholder values
CUST_FN="myextension.jar"
CUST_FULL="xNULLx"
while [ ! -f ${CUST_FULL} ]; do
echo -ne "\n${Green} Enter a valid filename of the .jar extension file (Ex: myextension.jar): ${Yellow}"
read CUST_FN
CUST_FN=${CUST_FN:-${CUST_FN}}
echo -n "${Green} Enter the full path of the dir containing the .jar extension file (must end with / Ex: /home/me/): ${Yellow}"
read CUST_DIR
CUST_DIR=${CUST_DIR:-/home/}
CUST_FULL=${CUST_DIR}${CUST_FN}
if [ ! -f ${CUST_FULL} ]; then # Check that full path/name exists, otherwise prompt again
echo "${Red} The file/path: ${CUST_FULL} does not exist! Ensure the file is in the directory and try again..."
fi
done
break;;
[Nn]*|"" ) INSTALL_CUST_EXT=false; break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
}
######################################################################
######################################################################
sum_menu () {
SUB_MENU_TITLE="Summary Menu"
menu_header
RUN_INSTALL=false
RET_SUM=false
echo "${Green} Select a category to review selections: ${Yellow}"
PS3="${Green} Enter the number of the category to review: ${Yellow}"
options=("Database" "Passwords" "SSL Cert Type" "Nginx" "Primary Authentication Extension" "2FA Extension" "Custom Extension" "Accept and Run Installation" "Cancel and Start Over" "Cancel and Exit Script")
select opt in "${options[@]}"
do
case $opt in
"Database") sum_db; break;;
"Passwords") sum_pw; break;;
"SSL Cert Type") sum_ssl; break;;
"Nginx") sum_nginx; break;;
"Primary Authentication Extension") sum_prime_auth_ext; break;;
"2FA Extension") sum_secondary_auth_ext; break;;
"Custom Extension") sum_cust_ext; break;;
"Accept and Run Installation") RUN_INSTALL=true; break;;
"Cancel and Start Over") ScriptLoc=$(readlink -f "$0"); exec "$ScriptLoc"; break;;
"Cancel and Exit Script") tput sgr0; exit 1; break;;
* ) echo "${Green} ${REPLY} is not a valid option, enter the number representing the category to review.";;
esac
done
}
sum_db () {
SUB_MENU_TITLE="Database Summary"
menu_header
echo "${Green} Guacamole DB name: ${Yellow}${DB_NAME}"
echo "${Green} Guacamole DB username: ${Yellow}${DB_USER}"
echo -e "${Green} Java KeyStore key-size: ${Yellow}${JKSTORE_KEY_SIZE}\n"
while true; do
echo -n "${Green} Would you like to change these selections (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) db_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
sum_pw () {
SUB_MENU_TITLE="Passwords Summary"
menu_header
echo "${Green} MariaDB root password: ${Yellow}${MYSQL_PASSWD}"
echo "${Green} Guacamole DB password: ${Yellow}${DB_PASSWD}"
echo -e "${Green} Guacamole Java KeyStore password: ${Yellow}${JKS_GUAC_PASSWD}\n"
while true; do
echo -n "${Green} Would you like to change these selections (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) pw_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
sum_ssl () {
SUB_MENU_TITLE="SSL Certificate Summary"
menu_header
echo -e "${Green} Certficate Type: ${Yellow}${SSL_CERT_TYPE}\n"
case $SSL_CERT_TYPE in
"LetsEncrypt")
echo "${Green} e-mail for LetsEncrypt certificate: ${Yellow}${EMAIL_NAME}"
echo "${Green} LetEncrypt key-size: ${Yellow}${LE_KEY_SIZE}"
echo -e "${Green} Use OCSP Stapling?: ${Yellow}${OCSP_USE}\n"
;;
"Self-signed")
echo -e "${Green} Self-Signed SSL key-size: ${Yellow}${SSL_KEY_SIZE}\n"
;;
"None")
echo -e "${Yellow} As no certificate type was selected, an SSL certificate can be configured manually at a later time.\n"
;;
esac
while true; do
echo -n "${Green} Would you like to change these selections (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) ssl_cert_type_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
sum_nginx () {
SUB_MENU_TITLE="Nginx Summary"
menu_header
echo "${Green} Guacamole Server LAN IP address: ${Yellow}${GUAC_LAN_IP}"
echo "${Green} Guacamole Server hostname or public domain: ${Yellow}${DOMAIN_NAME}"
echo "${Green} URI path: ${Yellow}${GUAC_URIPATH}"
echo "${Green} Using only 256-bit >= ciphers?: ${Yellow}${NGINX_SEC}"
echo -e "${Green} Content-Security-Policy [CSP] enabled?: ${Yellow}${USE_CSP}\n"
while true; do
echo -n "${Green} Would you like to change these selections (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) nginx_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
sum_prime_auth_ext () {
SUB_MENU_TITLE="Primary Authentication Extension Summary"
menu_header
echo -e "${Green} Primary Authentication type: ${Yellow}${PRIME_AUTH_TYPE}\n"
echo "${Yellow}${Bold} -- MariaDB is used with all authentication implementations --${Reset}"
echo "${Green} Default Guacamole username: ${Yellow}guacadmin"
echo -e "${Green} Default Guacamole password: ${Yellow}guacadmin\n"
case $PRIME_AUTH_TYPE in
"LDAP")
echo -e "${Reset}${Bold} -- LDAP Specific Parameters --${Reset}\n"
echo "${Green} Use LDAPS instead of LDAP: ${Yellow}${SECURE_LDAP}"
echo -e "${Green} LDAP(S) port: ${Yellow}${LDAP_PORT}\n"
if [ $SECURE_LDAP = true ]; then
echo "${Green} LDAPS full filename and path: ${Yellow}${LDAPS_CERT_FULL}"
echo -e "${Green} CACert Java Keystroe password: ${Yellow}${JKS_CACERT_PASSWD}\n"
fi
echo "${Green} LDAP Server Hostname (should be FQDN, Ex: ldaphost.domain.com): ${Yellow}${LDAP_HOSTNAME}"
echo "${Green} LDAP User-Base-DN (Ex: dc=domain,dc=com): ${Yellow}${LDAP_BASE_DN}"
echo "${Green} LDAP Search-Bind-DN (Ex: cn=user,ou=Admins,dc=domain,dc=com): ${Yellow}${LDAP_BIND_DN}"
echo "${Green} LDAP Search-Bind-Password: ${Yellow}${LDAP_BIND_PW}"
echo "${Green} LDAP Username-Attribute: ${Yellow}${LDAP_UNAME_ATTR}"
echo -e "${Green} LDAP user search filter: ${Yellow}${LDAP_SEARCH_FILTER}\n"
;;
"RADIUS")
echo -e "${Red} RADIUS cannot currently be installed by this script.\n"
;;
"OpenID")
echo -e "${Red} OpenID cannot currently be installed by this script.\n"
;;
"CAS")
echo -e "${Red} CAS cannot currently be installed by this script.\n"
;;
esac
while true; do
echo -n "${Green} Would you like to change the authentication method and properties (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) prime_auth_ext_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
sum_secondary_auth_ext () {
SUB_MENU_TITLE="2FA Extension Summary"
menu_header
echo -e "${Green} 2FA selection: ${Yellow}${TFA_TYPE}\n"
case $TFA_TYPE in
"None")
echo -e "${Yellow}${Bold} -- No form of 2FA will be implemented by this script --${Reset}\n"
;;
"TOTP")
echo "${Green} TOTP issuer: ${Yellow}${TOTP_ISSUER}"
echo "${Green} Number of TOTP digits: ${Yellow}${TOTP_DIGITS}"
echo "${Green} TOTP period in seconds: ${Yellow}${TOTP_PER}"
echo -e "${Green} TOTP mode: ${Yellow}${TOTP_MODE}\n"
;;
"DUO")
echo -e "${Red} DUO cannot currently be installed by this script.\n"
;;
esac
while true; do
echo -n "${Green} Would you like to change the 2FA method and properties (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) secondary_auth_ext_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
sum_cust_ext () {
SUB_MENU_TITLE="Custom Extension Summary"
menu_header
echo -e "${Green} Install a custom Guacamole extension: ${Yellow}${INSTALL_CUST_EXT}\n"
if [ $INSTALL_CUST_EXT = true ]; then
echo "${Green} Filename of the .jar extension file: ${Yellow}${CUST_FN}"
echo "${Green} Full path of the dir containing the .jar extension file: ${Yellow}${CUST_DIR}"
echo -e "${Green} Full file path: ${Yellow}${CUST_FULL}\n"
fi
while true; do
echo -n "${Green} Would you like to change these selections (default no)? ${Yellow}"
read yn
case $yn in
[Yy]* ) cust_ext_menu; break;;
[Nn]*|"" ) break;;
* ) echo "${Green} Please enter yes or no. ${Yellow}";;
esac
done
sum_menu
}
db_menu
pw_menu
ssl_cert_type_menu
nginx_menu
prime_auth_ext_menu
secondary_auth_ext_menu
cust_ext_menu
sum_menu
exec 3>&1
######################################################################
######################################################################
spinner () {
pid=$!
#Store the background process id in a temp file to use in err_handler
echo
spin[0]="-"
spin[1]="\"
spin[2]="|"
spin[3]="/"
while kill -0 $pid 2>/dev/null
do
for i in "${spin[@]}"
do
if kill -0 $pid 2>/dev/null; then #Check that the process is running to prevent a full 4 character cycle on error
# Display the spinner in 1/4 states
echo -ne "\b\b\b${Bold}[${Green}$i${Reset}${Bold}]" >&3
sleep .5 # time between each state
else #process has ended, stop next loop from finishing iteration
break
fi
done
done
if wait $pid; then # Exit 0
echo -ne "\b\b\b${Bold}[${Green}-done-${Reset}${Bold}]" >&3
else # Any other exit
false
fi
#Set background process id value to -1 representing no background process running to err_handler
echo "-1" > "${VAR_FILE}"
tput sgr0 >&3
}
s_echo () {
case $1 in
# No preceeding blank line
[Nn])
echo -ne "\n${2}" | tee -a /dev/fd/3
echo # add new line after in log only
;;
# Preceeding blank line
[Yy]|*)
echo -ne "\n\n${2}" | tee -a /dev/fd/3
echo # add new line after in log only
;;
esac
}
exec &> "${logfile}"
err_handler () {
EXITCODE=$?
#Read values from temp file used to store cross process values
F_BG=$(sed -n 1p "${VAR_FILE}")
if [
# If so, set variable according to value of the 2nd line in the file.
H_ERR=$(sed -n 2p "${VAR_FILE}")
else # Otherwise, set to false, error was not triggered previously
H_ERR=false
fi
#Check this is the first time the err_handler has triggered
if [ $H_ERR = false ]; then
#Check if error occured with a background process running
if [ $F_BG -gt 0 ]; then
echo -ne "\b\b\b${Bold}[${Red}-FAILED-${Reset}${Bold}]" >&3
fi
FAILED_COMMAND=$(eval echo "$BASH_COMMAND") # Used to expand the variables in the command returned by BASH_COMMAND
s_echo "y" "${Reset}${Red}%%% ${Reset}${Bold}ERROR (Script Failed) | Line${Reset} ${BASH_LINENO[0]} ${Bold}| Command:${Reset} ${FAILED_COMMAND} ${Bold}| Exit code:${Reset} ${EXITCODE} ${Red}%%%${Reset}\n\n"
#Flag as trap having been run already skipping double error messages
echo "true" >> "${VAR_FILE}"
fi
sed -i 's/\x1b[[0-9;]*m|\x1b[(]B\x1b[m//g' ${logfile}
tput sgr0 >&3
exit $EXITCODE
}
chk_installed () {
if rpm -q "$@"; then
RETVAL=$?
else
RETVAL=$?
fi
}
chk_repo_enabled () {
if grep -q "$@"; then
RETVAL=$?
else
RETVAL=$?
fi
}
trap err_handler ERR SIGINT SIGQUIT
######################################################################
######################################################################
reposinstall () {
s_echo "n" "${Bold} ----==== INSTALLING GUACAMOLE ${GUAC_SOURCE} ${GUAC_VER} ====----"
s_echo "y" "Installing Repos and mandatory software"
chk_installed "wget"
if [ $RETVAL -eq 0 ]; then
s_echo "n" "${Reset}-WGET is installed."
else
{ yum -y install wget; } &
s_echo "n" "${Reset}-WGET is missing. Installing... "; spinner
fi
chk_installed "make"
if [ $RETVAL -eq 0 ]; then
s_echo "n" "${Reset}-MAKE is installed."
else
{ yum -y install make; } &
s_echo "n" "${Reset}-MAKE is missing. Installing... "; spinner
fi
chk_installed "epel-release"
if [ $RETVAL -eq 0 ]; then
s_echo "n" "${Reset}-EPEL is installed."
else
{ rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-${MAJOR_VER}.noarch.rpm; } &
s_echo "n" "${Reset}-EPEL is missing. Installing... "; spinner
fi
chk_installed "rpmfusion-free-release"
if [ $RETVAL -eq 0 ]; then
s_echo "n" "-RPMFusion is installed."
else
{ rpm -Uvh https://download1.rpmfusion.org/free/el/rpmfusion-free-release-${MAJOR_VER}.noarch.rpm; } &
s_echo "n" "-RPMFusion is missing. Installing... "; spinner
fi
chk_installed "rpmfusion-nonfree-release"
if [ $RETVAL -eq 0 ]; then
s_echo "n" "-RPMFusion nonfree is installed."
else
{ rpm -Uvh https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-${MAJOR_VER}.noarch.rpm; } &
s_echo "n" "-RPMFusion is missing. Installing... "; spinner
fi
chk_installed "harbottle-main-release"
if [ $RETVAL -eq 0 ]; then
s_echo "n" "-harbottle is installed."
else
{ rpm -Uvh https://harbottle.gitlab.io/harbottle-main/${MAJOR_VER}/x86_64/harbottle-main-release.rpm; } &
s_echo "n" "-harbottle is missing. Installing... "; spinner
fi
chk_repo_enabled "enabled=1" /etc/yum.repos.d/almalinux-powertools.repo
if [ $RETVAL -eq 0 ]; then
s_echo "n" "-Powertools enabled."
else
{ dnf config-manager --enable powertools; } &
s_echo "n" "-PowerTools was not enabled, enabled "; spinner
fi
{ echo "[nginx-stable]
name=Nginx Stable Repo
baseurl=${NGINX_URL}
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true" > /etc/yum.repos.d/nginx.repo; } &
s_echo "n" "${Reset}-Installing Nginx repo... "; spinner
{
yum install -y wget
wget ${LIBJPEG_REPO} -P /etc/yum.repos.d/
# Exclude beta releases
sed -i "s/exclude.*/${LIBJPEG_EXCLUDE}/g" /etc/yum.repos.d/libjpeg-turbo.repo
} &
s_echo "n" "-Installing libjpeg-turbo repo... "; spinner
if [ $OS_NAME == "RHEL" ] ; then
{ subscription-manager repos --enable "rhel--optional-rpms" --enable "rhel--extras-rpms"; } &
s_echo "n" "-Enabling ${OS_NAME} optional and extras repos... "; spinner
fi
yumupdate
}
yumupdate () {
{ yum update -y; } &
s_echo "y" "${Bold}Updating ${OS_NAME}, please wait... "; spinner
baseinstall
}
baseinstall () {
s_echo "y" "${Bold}Installing Required Dependencies"
{
yum install -y cairo-devel ffmpeg-devel freerdp-devel freerdp-plugins gcc gnu-free-mono-fonts make libjpeg-turbo-devel libjpeg-turbo-official libpng-devel libssh2-devel libtelnet-devel libvncserver-devel libvorbis-devel libwebp-devel libwebsockets-devel mariadb mariadb-server nginx openssl-devel pango-devel policycoreutils-python-utils pulseaudio-libs-devel setroubleshoot ${TOMCAT_VER} uuid-devel
} &
s_echo "n" "${Reset}-Installing required packages... "; spinner
if [ $GUAC_SOURCE == "Git" ]; then
{ yum install -y git libtool java-1.8.0-openjdk-devel; } &
s_echo "n" "-Installing packages required for git... "; spinner
#Install Maven
cd /opt
{
wget ${MAVEN_URL}${MAVEN_BIN}
tar -xvzf ${MAVEN_BIN}
ln -s ${MAVEN_FN} maven
rm -rf /opt/${MAVEN_BIN}
} &
s_echo "n" "-Installing Apache Maven for git... "; spinner
export PATH=/opt/maven/bin:${PATH}
cd ~
fi
createdirs
}
createdirs () {
{
rm -fr ${INSTALL_DIR}
mkdir -vp /etc/guacamole
mkdir -vp ${INSTALL_DIR}{client,selinux}
mkdir -vp ${LIB_DIR}{extensions,lib}
mkdir -vp /usr/share/${TOMCAT_VER}/.guacamole/
} &
s_echo "y" "${Bold}Creating Required Directories... "; spinner
cd ${INSTALL_DIR}
downloadguac
}
downloadguac () {
s_echo "y" "${Bold}Downloading Guacamole Packages"
# MySQL Connector
downloadmysqlconn () {
{ wget ${MYSQL_CON_URL}${MYSQL_CON}.tar.gz; } &
s_echo "n" "-Downloading MySQL Connector package for installation... "; spinner
}
if [ $GUAC_SOURCE == "Git" ]; then
{ git clone ${GUAC_URL}${GUAC_SERVER}; } &
s_echo "n" "${Reset}-Cloning Guacamole Server package from git... "; spinner
{ git clone ${GUAC_URL}${GUAC_CLIENT}; } &
s_echo "n" "-Cloning Guacamole Client package from git... "; spinner
downloadmysqlconn
else # Stable release
{ wget "${GUAC_URL}source/${GUAC_SERVER}.tar.gz" -O ${GUAC_SERVER}.tar.gz; } &
s_echo "n" "${Reset}-Downloading Guacamole Server package for installation... "; spinner
{ wget "${GUAC_URL}binary/${GUAC_CLIENT}.war" -O ${INSTALL_DIR}client/guacamole.war; } &
s_echo "n" "-Downloading Guacamole Client package for installation... "; spinner
{ wget "${GUAC_URL}binary/${GUAC_JDBC}.tar.gz" -O ${GUAC_JDBC}.tar.gz; } &
s_echo "n" "-Downloading Guacamole JDBC Extension package for installation... "; spinner
downloadmysqlconn
# Decompress Guacamole Packages
s_echo "y" "${Bold}Decompressing Guacamole Packages"
{
tar xzvf ${GUAC_SERVER}.tar.gz
rm -f ${GUAC_SERVER}.tar.gz
mv -v ${GUAC_SERVER} server
} &
s_echo "n" "${Reset}-Decompressing Guacamole Server source... "; spinner
{
tar xzvf ${GUAC_JDBC}.tar.gz
rm -f ${GUAC_JDBC}.tar.gz
mv -v ${GUAC_JDBC} extension
mv -v extension/mysql/guacamole-auth-jdbc-mysql-${GUAC_VER}.jar ${LIB_DIR}extensions/
} &
s_echo "n" "-Decompressing Guacamole JDBC extension... "; spinner
fi
{
tar xzvf ${MYSQL_CON}.tar.gz
rm -f ${MYSQL_CON}.tar.gz
mv -v ${MYSQL_CON}/${MYSQL_CON}.jar ${LIB_DIR}lib/
} &
s_echo "n" "-Decompressing MySQL Connector... "; spinner
installguacserver
}
installguacserver () {
s_echo "y" "${Bold}Install Guacamole Server"
if [ $GUAC_SOURCE == "Git" ]; then
cd guacamole-server/
{ autoreconf -fi; } &
s_echo "n" "${Reset}-Guacamole Server compile prep... "; spinner
else # Stable release
cd server
fi
{ ./configure --with-systemd-dir=/usr/lib/systemd/system/; } &
s_echo "n" "${Reset}-Compiling Guacamole Server Stage 1 of 4... "; spinner
{ make; } &
s_echo "n" "-Compiling Guacamole Server Stage 2 of 4... "; spinner
{ make install; } &
s_echo "n" "-Compiling Guacamole Server Stage 3 of 4... "; spinner
{ ldconfig; } &
s_echo "n" "-Compiling Guacamole Server Stage 4 of 4... "; spinner
cd ..
installguacclient
}
installguacclient () {
s_echo "y" "${Bold}Install Guacamole Client"
if [ $GUAC_SOURCE == "Git" ]; then
cd guacamole-client/
{ mvn package; } &
s_echo "n" "${Reset}-Compiling Guacamole Client... "; spinner
{ mv -v guacamole/target/guacamole-${GUAC_VER}.war ${LIB_DIR}guacamole.war; } &
s_echo "n" "-Moving Guacamole Client... "; spinner
cd ..
else # Stable release
{ mv -v client/guacamole.war ${LIB_DIR}guacamole.war; } &
s_echo "n" "${Reset}-Moving Guacamole Client... "; spinner
fi
finishguac
}
finishguac () {
s_echo "y" "${Bold}Setup Guacamole"
{ echo "# Hostname and port of guacamole proxy
guacd-hostname: localhost
guacd-port: ${GUAC_PORT}
mysql-hostname: localhost
mysql-port: ${MYSQL_PORT}
mysql-database: ${DB_NAME}
mysql-username: ${DB_USER}
mysql-password: ${DB_PASSWD}
mysql-default-max-connections-per-user: 0
mysql-default-max-group-connections-per-user: 0" > /etc/guacamole/${GUAC_CONF}; } &
s_echo "n" "${Reset}-Generating Guacamole configuration file... "; spinner
{
ln -vfs ${LIB_DIR}guacamole.war /var/lib/${TOMCAT_VER}/webapps
ln -vfs /etc/guacamole/${GUAC_CONF} /usr/share/${TOMCAT_VER}/.guacamole/
ln -vfs ${LIB_DIR}lib/ /usr/share/${TOMCAT_VER}/.guacamole/
ln -vfs ${LIB_DIR}extensions/ /usr/share/${TOMCAT_VER}/.guacamole/
ln -vfs /usr/local/lib/freerdp/guac* /usr/lib${ARCH}/freerdp
} &
s_echo "n" "-Making required symlinks... "; spinner
if [ $GUAC_SOURCE == "Git" ]; then
# Get JDBC from compiled client
{ find ./guacamole-client/extensions -name "guacamole-auth-jdbc-mysql-${GUAC_VER}.jar" -exec mv -v {} ${LIB_DIR}extensions/ ;; } &
s_echo "n" "-Moving Guacamole JDBC extension to extensions dir... "; spinner
fi
{
# Create a user and group for guacd with a home folder but no login
groupadd ${GUACD_USER}
# The guacd user is created as a service account, no login but does get a home dir as needed by freerdp
useradd -r ${GUACD_USER} -m -s "/bin/nologin" -g ${GUACD_USER} -c ${GUACD_USER}
# Set the user that runs the guacd service
sed -i "s/User=daemon/User=${GUACD_USER}/g" /usr/lib/systemd/system/guacd.service
} &
s_echo "n" "-Setup guacd user... "; spinner
appconfigs
}
appconfigs () {
s_echo "y" "${Bold}Configure MariaDB"
{
systemctl enable mariadb.service
systemctl restart mariadb.service
} &
s_echo "n" "${Reset}-Enable & start MariaDB service... "; spinner
{ mysqladmin -u root password ${MYSQL_PASSWD}; } &
s_echo "n" "-Setting root password for MariaDB... "; spinner
{
mysql_secure_installation <<EOF
${MYSQL_PASSWD}
n
y
y
y
y
EOF
} &
s_echo "n" "-Harden MariaDB... "; spinner
{
mysql -u root -p${MYSQL_PASSWD} -e "CREATE DATABASE ${DB_NAME};"
mysql -u root -p${MYSQL_PASSWD} -e "GRANT SELECT,INSERT,UPDATE,DELETE ON ${DB_NAME}.* TO '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASSWD}';"
mysql -u root -p${MYSQL_PASSWD} -e "FLUSH PRIVILEGES;"
} &
s_echo "n" "-Creating Database & User for Guacamole... "; spinner
{
if [ $GUAC_SOURCE == "Git" ]; then
cat guacamole-client/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/.sql | mysql -u root -p${MYSQL_PASSWD} -D ${DB_NAME}
else # Stable release
cat extension/mysql/schema/.sql | mysql -u root -p${MYSQL_PASSWD} -D ${DB_NAME}
fi
} &
s_echo "n" "-Creating Guacamole Tables... "; spinner
{
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p${MYSQL_PASSWD}
MY_CNF_LINE=grep -n "\[mysqld\]" /etc/my.cnf.d/mariadb-server.cnf | grep -o '^[0-9]*'
# MY_CNF_LINE=grep -n "\[mysqld\]" /etc/my.cnf | grep -o '^[0-9]*'
MY_CNF_LINE=$((MY_CNF_LINE + 1 ))
MY_TZ=readlink /etc/localtime | sed "s/.*\/usr\/share\/zoneinfo\///"
sed -i "${MY_CNF_LINE}i default-time-zone='${MY_TZ}'" /etc/my.cnf.d/mariadb-server.cnf
systemctl restart mariadb
} &
s_echo "n" "-Setting Time Zone Database & Config... "; spinner
s_echo "y" "${Bold}Setup Tomcat Server"
{
sed -i '72i URIEncoding="UTF-8"' /etc/${TOMCAT_VER}/server.xml
sed -i '92i <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="/var/lib/${TOMCAT_VER}/webapps/.keystore"
keystorePass="JKS_GUAC_PASSWD"
URIEncoding="UTF-8" />' /etc/${TOMCAT_VER}/server.xml
sed -i "s/JKS_GUAC_PASSWD/${JKS_GUAC_PASSWD}/g" /etc/${TOMCAT_VER}/server.xml
} &
s_echo "n" "${Reset}-Base Tomcat configuration... "; spinner
{
sed -i '/<\/Host>/i\<Valve className="org.apache.catalina.valves.RemoteIpValve" \
internalProxies="GUAC_SERVER_IP" \
remoteIpHeader="x-forwarded-for" \
remoteIpProxiesHeader="x-forwarded-by" \
protocolHeader="x-forwarded-proto" />' /etc/${TOMCAT_VER}/server.xml
sed -i "s/GUAC_SERVER_IP/${GUAC_LAN_IP}/g" /etc/${TOMCAT_VER}/server.xml
} &
s_echo "n" "-Set RemoteIpValve in Tomcat configuration... "; spinner
{
sed -i '/<\/Host>/i\<Valve className="org.apache.catalina.valves.ErrorReportValve" \
showReport="false" \
showServerInfo="false"/>' /etc/${TOMCAT_VER}/server.xml
} &
s_echo "n" "-Set ErrorReportingVavle in ${TOMCAT_VER}n... "; spinner
{ keytool -genkey -alias Guacamole -keyalg RSA -keysize ${JKSTORE_KEY_SIZE} -keystore /var/lib/${TOMCAT_VER}/webapps/.keystore -storepass ${JKS_GUAC_PASSWD} -keypass ${JKS_GUAC_PASSWD} -noprompt -dname "CN='', OU='', O='', L='', S='', C=''"; } &
s_echo "y" "${Bold}Configuring the Java KeyStore... "; spinner
{
systemctl enable ${TOMCAT_VER}
systemctl restart ${TOMCAT_VER}
systemctl enable guacd
systemctl restart guacd
} &
s_echo "y" "${Bold}Enable & Start Tomcat and Guacamole Services... "; spinner
nginxcfg
}
nginxcfg () {
s_echo "y" "${Bold}Nginx Configuration"
{ mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.ori.bkp; } &
s_echo "n" "${Reset}-Making Nginx config backup... "; spinner
{ echo "server {
listen 80;
listen [::]:80;
server_name ${DOMAIN_NAME};
return 301 https://$host$request_uri;
location ${GUAC_URIPATH} {
proxy_pass http://${GUAC_LAN_IP}:8080/guacamole/;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection \$http_connection;
proxy_cookie_path /guacamole/ ${GUAC_URIPATH};
access_log off;
}
}" > /etc/nginx/conf.d/guacamole.conf
} &
s_echo "n" "${Reset}-Generate Nginx guacamole.config... "; spinner
{
echo "server {
#listen 443 ssl http2 default_server;
#listen [::]:443 ssl http2 default_server;
server_name ${DOMAIN_NAME};
server_tokens off;
#ssl_certificate guacamole.crt;
#ssl_certificate_key guacamole.key; " > /etc/nginx/conf.d/guacamole_ssl.conf
# If OCSP Stapling was selected add lines
if [ $OCSP_USE = true ]; then
if [[ -r /etc/resolv.conf ]]; then
NAME_SERVERS=$(awk '/^nameserver/{print $2}' /etc/resolv.conf | xargs)
fi
if [[ -z $NAME_SERVERS ]]; then
NAME_SERVERS=$NAME_SERVERS_DEF
fi
echo " #ssl_trusted_certificate guacamole.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver ${NAME_SERVERS} valid=30s;
resolver_timeout 30s;" >> /etc/nginx/conf.d/guacamole_ssl.conf
fi
# If using >= 256-bit ciphers
if [ $NGINX_SEC = true ]; then
echo " ssl_ciphers 'TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384';" >> /etc/nginx/conf.d/guacamole_ssl.conf
else
echo " ssl_ciphers 'TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256';" >> /etc/nginx/conf.d/guacamole_ssl.conf
fi
# Rest of HTTPS/SSL Nginx Conf
echo " ssl_protocols TLSv1.3 TLSv1.2;
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Referrer-Policy \"no-referrer\";
add_header Strict-Transport-Security \"max-age=15768000; includeSubDomains\" always;" >> /etc/nginx/conf.d/guacamole_ssl.conf
# If CSP was enabled, add line, otherwise add but comment out (to allow easily manual toggle of the feature)
if [ $USE_CSP = true ]; then
echo " add_header Content-Security-Policy \"default-src 'none'; script-src 'self' 'unsafe-eval'; connect-src 'self' wss://${DOMAIN_NAME}; object-src 'self'; frame-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; form-action 'self'; base-uri 'self'; frame-ancestors 'self';\" always;" >> /etc/nginx/conf.d/guacamole_ssl.conf
else
echo " #add_header Content-Security-Policy \"default-src 'none'; script-src 'self' 'unsafe-eval'; connect-src 'self' wss://${DOMAIN_NAME}; object-src 'self'; frame-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; form-action 'self'; base-uri 'self'; frame-ancestors 'self';\" always;" >> /etc/nginx/conf.d/guacamole_ssl.conf
fi
echo " add_header X-Frame-Options \"SAMEORIGIN\" always;
add_header X-Content-Type-Options \"nosniff\" always;
add_header X-XSS-Protection \"1; mode=block\" always;
proxy_hide_header Server;
proxy_hide_header X-Powered-By;
client_body_timeout 10;
client_header_timeout 10;
location ${GUAC_URIPATH} {
proxy_pass http://${GUAC_LAN_IP}:8080/guacamole/;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection \$http_connection;
proxy_cookie_path /guacamole/ \"${GUAC_URIPATH}; HTTPOnly; Secure; SameSite\";
access_log /var/log/nginx/guac_access.log;
error_log /var/log/nginx/guac_error.log;
}
}" >> /etc/nginx/conf.d/guacamole_ssl.conf
} &
s_echo "n" "-Generate Nginx guacamole_ssl.config... "; spinner
{
# 2.3.2 Restrict access to Nginx files
find /etc/nginx -type d | xargs chmod 750
find /etc/nginx -type f | xargs chmod 640
# 2.4.3 & 2.4.4 set keepalive_timeout and send_timeout to 1-10 seconds, default 65/60.
sed -i '/keepalive_timeout/c\keepalive_timeout 10\;' /etc/nginx/nginx.conf
# sed -i '/send_timeout/c\send_timeout 10\;' /etc/nginx/nginx.conf
# 2.5.2 Reoving mentions of Nginx from index and error pages
! read -r -d '' BLANK_HTML <<"EOF"
echo "${BLANK_HTML}" > /usr/share/nginx/html/index.html
echo "${BLANK_HTML}" > /usr/share/nginx/html/50x.html
# 3.4 Ensure logs are rotated (may set this as a user defined parameter)
sed -i "s/daily/weekly/" /etc/logrotate.d/nginx
sed -i "s/rotate 52/rotate 13/" /etc/logrotate.d/nginx
} &
s_echo "n" "-Hardening Nginx config... "; spinner
{
systemctl enable nginx
systemctl restart nginx
} &
s_echo "n" "-Enable & Start Nginx Service... "; spinner
if [ $INSTALL_LDAP = true ]; then ldapsetup; fi
if [ $INSTALL_TOTP = true ]; then totpsetup; fi
if [ $INSTALL_DUO = true ]; then duosetup; fi
if [ $INSTALL_RADIUS = true ]; then radiussetup; fi
if [ $INSTALL_CAS = true ]; then cassetup; fi
if [ $INSTALL_OPENID = true ]; then openidsetup; fi
if [ $INSTALL_CUST_EXT = true ]; then custsetup; fi
selinuxsettings
}
ldapsetup () {
s_echo "y" "${Bold}Setup the LDAP Extension"
{ echo "
ldap-hostname: ${LDAP_HOSTNAME}
ldap-port: ${LDAP_PORT}" >> /etc/guacamole/${GUAC_CONF}; } &
s_echo "n" "${Reset}-Updating guacamole.properties file for LDAP... "; spinner
if [ $SECURE_LDAP = true ]; then
{
KS_PATH=$(find "/usr/lib/jvm/" -name "cacerts")
keytool -storepasswd -new ${JKS_CACERT_PASSWD} -keystore ${KS_PATH} -storepass "changeit"
keytool -importcert -alias "ldaps" -keystore ${KS_PATH} -storepass ${JKS_CACERT_PASSWD} -file ${LDAPS_CERT_FULL} -noprompt
echo "ldap-encryption-method: ssl" >> /etc/guacamole/${GUAC_CONF}
} &
s_echo "n" "-Updating guacamole.properties file for LDAPS... "; spinner
fi
{ echo "ldap-user-base-dn: ${LDAP_BASE_DN}
ldap-search-bind-dn: ${LDAP_BIND_DN}
ldap-search-bind-password: ${LDAP_BIND_PW}
ldap-username-attribute: ${LDAP_UNAME_ATTR}
ldap-user-search-filter: ${LDAP_SEARCH_FILTER}
mysql-auto-create-accounts: true" >> /etc/guacamole/${GUAC_CONF}; } &
s_echo "n" "-Finishing updates to the guacamole.properties file for LDAP... "; spinner
if [ $GUAC_SOURCE == "Git" ]; then
# Copy LDAP Extension to Extensions Directory
{ find ./guacamole-client/extensions -name "${GUAC_LDAP}.jar" -exec mv -v {} ${LIB_DIR}extensions/ ;; } &
s_echo "n" "-Moving Guacamole LDAP extension to extensions dir... "; spinner
else # Stable release
# Download LDAP Extension
{ wget "${GUAC_URL}binary/${GUAC_LDAP}.tar.gz" -O ${GUAC_LDAP}.tar.gz; } &
s_echo "n" "-Downloading LDAP extension... "; spinner
# Decompress LDAP Extension
{
tar xzvf ${GUAC_LDAP}.tar.gz
rm -f ${GUAC_LDAP}.tar.gz
mv ${GUAC_LDAP} extension
} &
s_echo "n" "-Decompressing Guacamole LDAP Extension... "; spinner
# Copy LDAP Extension to Extensions Directory
{ mv -v extension/${GUAC_LDAP}/${GUAC_LDAP}.jar ${LIB_DIR}extensions/; } &
s_echo "n" "-Moving Guacamole LDAP extension to extensions dir... "; spinner
fi
}
totpsetup () {
s_echo "y" "${Bold}Setup the TOTP Extension"
{ echo "
totp-issuer: ${TOTP_ISSUER}
totp-digits: ${TOTP_DIGITS}
totp-period: ${TOTP_PER}
totp-mode: ${TOTP_MODE}" >> /etc/guacamole/${GUAC_CONF}; } &
s_echo "n" "${Reset}-Updating guacamole.properties file for TOTP... "; spinner
if [ $GUAC_SOURCE == "Git" ]; then
{ find ./guacamole-client/extensions -name "${GUAC_TOTP}.jar" -exec mv -v {} ${LIB_DIR}extensions/ ;; } &
s_echo "n" "-Moving Guacamole TOTP extension to extensions dir... "; spinner
else # Stable release
{ wget "${GUAC_URL}binary/${GUAC_TOTP}.tar.gz" -O ${GUAC_TOTP}.tar.gz; } &
s_echo "n" "-Downloading TOTP extension... "; spinner
{
tar xzvf ${GUAC_TOTP}.tar.gz
rm -f ${GUAC_TOTP}.tar.gz
mv ${GUAC_TOTP} extension
} &
s_echo "n" "-Decompressing Guacamole TOTP Extension... "; spinner
{ mv -v extension/${GUAC_TOTP}/${GUAC_TOTP}.jar ${LIB_DIR}extensions/; } &
s_echo "n" "-Moving Guacamole TOTP extension to extensions dir... "; spinner
fi
}
duosetup () {
# Placehold until extension is added
echo "duosetup"
}
radiussetup () {
# Placehold until extension is added
echo "radiussetup"
}
cassetup () {
# Placehold until extension is added
echo "cassetup"
}
openidsetup () {
# Placehold until extension is added
echo "openidsetup"
}
custsetup () {
{ mv -v ${CUST_FULL} ${LIB_DIR}extensions/; } &
s_echo "y" "${Bold}Copying Custom Guacamole Extension to Extensions Dir... "; spinner
}
selinuxsettings () {
{
# Set Booleans
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_relay 1
setsebool -P tomcat_can_network_connect_db 1
# Guacamole Client Context
semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}guacamole.war"
restorecon -v "${LIB_DIR}guacamole.war"
# Guacamole JDBC Extension Context
semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/guacamole-auth-jdbc-mysql-${GUAC_VER}.jar"
restorecon -v "${LIB_DIR}extensions/guacamole-auth-jdbc-mysql-${GUAC_VER}.jar"
# MySQL Connector Extension Context
semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}lib/${MYSQL_CON}.jar"
restorecon -v "${LIB_DIR}lib/${MYSQL_CON}.jar"
# Guacamole LDAP Extension Context (If selected)
if [ $INSTALL_LDAP = true ]; then
semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
restorecon -v "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
fi
# Guacamole TOTP Extension Context (If selected)
if [ $INSTALL_TOTP = true ]; then
# Placehold until extension is added
# echo "totp true"
semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${GUAC_TOTP}.jar"
restorecon -v "${LIB_DIR}extensions/${GUAC_TOTP}.jar"
fi
# Guacamole Duo Extension Context (If selected)
if [ $INSTALL_DUO = true ]; then
# Placehold until extension is added
echo "duo true"
#semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
#restorecon -v "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
fi
# Guacamole RADIUS Extension Context (If selected)
if [ $INSTALL_RADIUS = true ]; then
# Placehold until extension is added
echo "radius true"
#semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
#restorecon -v "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
fi
# Guacamole CAS Extension Context (If selected)
if [ $INSTALL_CAS = true ]; then
# Placehold until extension is added
echo "cas true"
#semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
#restorecon -v "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
fi
# Guacamole OpenID Extension Context (If selected)
if [ $INSTALL_OPENID = true ]; then
# Placehold until extension is added
echo "openid true"
#semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
#restorecon -v "${LIB_DIR}extensions/${GUAC_LDAP}.jar"
fi
# Guacamole Custom Extension Context (If selected)
if [ $INSTALL_CUST_EXT = true ]; then
semanage fcontext -a -t tomcat_exec_t "${LIB_DIR}extensions/${CUST_FN}"
restorecon -v "${LIB_DIR}extensions/${CUST_FN}"
fi
} &
s_echo "y" "${Bold}Setting SELinux Context... "; spinner
sestatus
firewallsettings
}
firewallsettings () {
s_echo "y" "${Bold}Firewall Configuration"
chk_installed "firewalld"
{
if [ $RETVAL -eq 0 ]; then
systemctl enable firewalld
systemctl restart firewalld
fi
} &
s_echo "n" "${Reset}-firewalld is installed and started on the system... "; spinner
{ cp /etc/firewalld/zones/public.xml $fwbkpfile; } &
s_echo "n" "-Backing up firewall public zone to: $fwbkpfile "; spinner
{
echo -e "Add new rule...\nfirewall-cmd --permanent --zone=public --add-service=http"
firewall-cmd --permanent --zone=public --add-service=http
echo -e "Add new rule...\nfirewall-cmd --permanent --zone=public --add-service=https"
firewall-cmd --permanent --zone=public --add-service=https
} &
s_echo "n" "-Opening HTTP and HTTPS service ports... "; spinner
{
echo -e "Add new rule...\nfirewall-cmd --permanent --zone=public --add-port=8080/tcp"
firewall-cmd --permanent --zone=public --add-port=8080/tcp
echo -e "Add new rule...\nfirewall-cmd --permanent --zone=public --add-port=8443/tcp"
firewall-cmd --permanent --zone=public --add-port=8443/tcp
} &
s_echo "n" "-Opening ports 8080 and 8443 on TCP... "; spinner
#echo -e "Reload firewall...\nfirewall-cmd --reload\n"
{ firewall-cmd --reload; } &
s_echo "n" "-Reloading firewall... "; spinner
sslcerts
}
sslcerts () {
s_echo "y" "${Bold}SSL Certificate Configuration"
if [ $SSL_CERT_TYPE != "None" ]; then
# Lets Encrypt Setup (If selected)
if [ $SSL_CERT_TYPE = "LetsEncrypt" ]; then
# Install certbot from repo
{ yum install -y certbot python2-certbot-nginx; } &
s_echo "n" "${Reset}-Downloading certboot tool... "; spinner
# OCSP
{
if [ $OCSP_USE = true ]; then
certbot certonly --nginx --must-staple -n --agree-tos --rsa-key-size ${LE_KEY_SIZE} -m "${EMAIL_NAME}" -d "${DOMAIN_NAME}"
else # Generate without OCSP --must-staple
certbot certonly --nginx -n --agree-tos --rsa-key-size ${LE_KEY_SIZE} -m "${EMAIL_NAME}" -d "${DOMAIN_NAME}"
fi
} &
s_echo "n" "-Generating a ${SSL_CERT_TYPE} SSL Certificate... "; spinner
# Symlink Lets Encrypt certs so renewal does not break Nginx
{
ln -vs "/etc/letsencrypt/live/${DOMAIN_NAME}/fullchain.pem" /etc/nginx/guacamole.crt
ln -vs "/etc/letsencrypt/live/${DOMAIN_NAME}/privkey.pem" /etc/nginx/guacamole.key
ln -vs "/etc/letsencrypt/live/${DOMAIN_NAME}/chain.pem" /etc/nginx/guacamole.pem
} &
s_echo "n" "-Creating symlinks to ${SSL_CERT_TYPE} SSL certificates... "; spinner
# Setup automatic cert renewal
{
systemctl enable certbot-renew.service
systemctl enable certbot-renew.timer
systemctl list-timers --all | grep certbot
} &
s_echo "n" "-Setup automatic ${SSL_CERT_TYPE} SSL certificate renewals... "; spinner
else # Use a Self-Signed Cert
{ openssl req -x509 -sha512 -nodes -days 365 -newkey rsa:${SSL_KEY_SIZE} -keyout /etc/nginx/guacamole.key -out /etc/nginx/guacamole.crt -subj "/C=''/ST=''/L=''/O=''/OU=''/CN=''"; } &
s_echo "n" "${Reset}-Generating ${SSL_CERT_TYPE} SSL Certificate... "; spinner
fi
# Nginx CIS v1.0.0 - 4.1.3 ensure private key permissions are restricted
{
ls -l /etc/nginx/guacamole.key
chmod 400 /etc/nginx/guacamole.key
} &
s_echo "n" "${Reset}-Changing permissions on SSL private key... "; spinner
{
# Uncomment listen lines from Nginx guacamole_ssl.conf (fixes issue introduced by Nginx 1.16.0)
sed -i 's/#\(listen.*443.*\)/\1/' /etc/nginx/conf.d/guacamole_ssl.conf
# Uncomment cert lines from Nginx guacamole_ssl.conf
sed -i 's/#\(.*ssl_.*certificate.*\)/\1/' /etc/nginx/conf.d/guacamole_ssl.conf
} &
s_echo "n" "${Reset}-Enabling SSL certificate in guacamole_ssl.conf... "; spinner
HTTPS_ENABLED=true
else # Cert is set to None
s_echo "n" "${Reset}-No SSL Cert selected..."
# Will not force/use HTTPS without a cert, comment out redirect
{ sed -i '/\(return 301 https\)/s/^/#/' /etc/nginx/conf.d/guacamole.conf; } &
s_echo "n" "${Reset}-Update guacamole.conf to allow HTTP connections... "; spinner
HTTPS_ENABLED=false
fi
showmessages
}
showmessages () {
s_echo "y" "${Bold}Services"
{
systemctl restart ${TOMCAT_VER}
systemctl status ${TOMCAT_VER}
systemctl restart guacd
systemctl status guacd
systemctl restart mariadb
systemctl status mariadb
systemctl restart nginx
systemctl status nginx
# Verify that the guacd user is running guacd
ps aux | grep ${GUACD_USER}
ps -U ${GUACD_USER}
} &
s_echo "n" "${Reset}-Restarting all services... "; spinner
s_echo "y" "${Bold}${Green}##### Installation Complete! #####${Reset}"
s_echo "y" "${Bold}Log Files"
s_echo "n" "${Reset}-Log file: ${logfile}"
s_echo "n" "-firewall backup file: ${fwbkpfile}"
if [ ${DOMAIN_NAME} = "localhost" ]; then
GUAC_URL=${GUAC_LAN_IP}${GUAC_URIPATH}
else # Not localhost
GUAC_URL=${DOMAIN_NAME}${GUAC_URIPATH}
fi
if [ ${HTTPS_ENABLED} = true ]; then
HTTPS_MSG="${Reset} or ${Bold}https://${GUAC_URL}${Reset}"
else # HTTPS not used
HTTPS_MSG="${Reset}. Without a cert, HTTPS is not forced/available."
fi
s_echo "y" "${Bold}To manage Guacamole"
s_echo "n" "${Reset}-go to: ${Bold}http://${GUAC_URL}${HTTPS_MSG}"
s_echo "n" "-The default username and password are: ${Red}guacadmin"
s_echo "y" "Important Recommendations${Reset}"
if [ $INSTALL_LDAP = false ]; then
s_echo "n" "-It is highly recommended to create an admin account in Guacamole and delete/disable the default asap!"
else
s_echo "n" "-You should assign at least one AD/LDAP user to have full admin, see the directions on how-to at:"
s_echo "n" "${Green} https://github.com/Zer0CoolX/guacamole-install-rhel-7/wiki/LDAP-or-LDAPS-Authentication#important-manual-steps${Reset}"
s_echo "n" "-Afterwards, it is highly recommended to delete/disable the default admin account and/or create a uniquely named local admin account asap!"
if [ $SECURE_LDAP = true ]; then
s_echo "n" "-Its highly recommended to remove the LDAPS certificate file from: ${LDAPS_CERT_FULL}"
fi
fi
s_echo "y" "${Green}While not technically required, you should consider a reboot after verifying installation${Reset}"
s_echo "y" "${Bold}Contact ${Reset}${ADM_POC}${Bold} with any questions or concerns regarding this script\n"
sed -i 's/\x1b[[0-9;]*m|\x1b[(]B\x1b[m//g' ${logfile}
tput sgr0 >&3
}
if [ ${RUN_INSTALL} = true ]; then
tput sgr0 >&3
clear >&3
reposinstall
if [ $DEL_TMP_VAR = true ]; then
rm "$VAR_FILE"
fi
exit 0
fi
`
You can see parts where i added fwe things to allow running into AlmaLinux 8
Hope it helps
Bye!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.