#!/bin/bash
VERSION=2
#************************************************
# Evaluate Install
#***********************************************
#Get full name of the directory we are in.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"


NOUSERINPUT=false

outputit () {
	if $NOUSERINPUT ; then
		echo -e "${1}:::"
	else
		echo -e "${1}"
	fi
}

cleanup () {
	outputit "Cleanup"
	#rm -r ${DIR}/tmpfiles
	#rm ${DESTDIR}/getKey.php
}

cleanupAll () {
	cleanup
	#cd ..
	#rm install.zip
	#rm -r install
}

usage() { 
	echo "Usage: $0 -[fgns] -i <installation name> -m <modules> [-t <title>] [-p <purchaser company>] [-q <purchaser name>] [-l <limit 1>] [-j limit 2]"
	echo "   [-k limit 3] [-u <admin username>] [-v <admin initial password>] [-T <timezone>] " 1>&2
	echo "      -i Manadatory parameter for the installation name"
	echo "      -m Manadatory parameter for the modules to install 1 - Score 2 - Room 3 - Both"
	echo "      -s Optional the web site is SSL and a cert is required"
	echo "      -t Title of the evalution instance"
	echo "      -l Optional Sets limit 1 (Number of evaluators) Default is 10 if not set"
	echo "      -j Optional Sets limit 2 (Number of evaluations) Default is 1 if not set"
	echo "      -k Optional Sets limit 3 (Number of administrators) Default is 1 if not set"
	echo "      -n Optional Not interactive, will not interface with console"
	echo "      -a Optional web root [Default is /var/www/html]" 
	echo "      -d Options root dns name [Default nvaluate.com]"
	echo "		-f Copy files only, do not install database or website"
	echo "		-g Copy files and install database only, do not install website"
	echo "		-p purchaeser company name"
	echo "		-q purchaeser name"
	echo "		-u admin username"
	echo "		-v admin password"
	echo "		-T timezone in php format default is Pacific/Auckland"
	echo "   Example: install.sh -i mytest -p Pw564DFS -s -n"
	exit 1
}

#Some defines
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' 

APACHEROOT="/var/www/html"
ROOTDNSNAME="nvaluate.com"
LIMIT1=10
LIMIT2=1
LIMIT3=1
INSTALLNAME=""
ADMINUSERNAME=""
ADMINPASSWORD=""
TIMEZONE="Pacific/Auckland"
PURCHASECOMPANY=""
PURCHASENAME=""
MODULES=0
NOUSERINPUT=false
SSL=false
INSTALLWEBSITE=true
INSTALLDATABASE=true
INSTALLBACKUPS=true
INSTALLKEYS=true
VAULTDIR="/etc/vault"

outputit "Running from directory: $DIR";

i=1;
for user in "$@" 
do
	outputit "Parameter - $i: $user";
	i=$((i + 1));
done

outputit "while loop start"
#parse options

while getopts ":a:d:fgi:l:j:k:m:np:q:st:u:v:T:" o; do
	outputit "Parameter: ${o} arg: ${OPTARG}"
	case "${o}" in
		a)
			APACHEROOT=${OPTARG}
			;;
		d)
			ROOTDNSNAME=${OPTARG}
			;;
		f)
			INSTALLBACKUPS=false
			INSTALLDATABASE=false
			INSTALLWEBSITE=false
			INSTALLKEYS=false
			;;
		g)
			INSTALLBACKUPS=false
			INSTALLWEBSITE=false
			;;
		i)
			INSTALLNAME=${OPTARG}
			;;
		l)
			LIMIT1=${OPTARG}
			;;
		j)
			LIMIT2=${OPTARG}
			;;
		k)
			LIMIT3=${OPTARG}
			;;
		m)
			MODULES=${OPTARG}
			;;
		n)
			NOUSERINPUT=true
			;;
		p)
			PURCHASECOMPANY=${OPTARG}
			;;
		q)
			PURCHASENAME=${OPTARG}
			;;
		s)
			SSL=true
			;;
		t)
			TITLE=${OPTARG}
			;;
		u)
			ADMINUSERNAME=${OPTARG}
			;;
		v)
			ADMINPASSWORD=${OPTARG}
			;;
		T)
			TIMEZONE=${OPTARG}
			;;
	   *)
			usage
			;;
	esac
done


outputit "-u = $ADMINUSERNAME"
outputit "-v = $ADMINPASSWORD"


if [ "$EUID" -ne 0 ]; then
  echo -e "${RED}ERROR: Please run as root with sudo${NC}" >&2
  exit 1
fi

#Check that the vault has been installed
if [ ! -d "$VAULTDIR" ]; then
	echo  -e "${RED}ERROR: The vault has not been configiured on this server, please install the vault and restart this install${NC}"
	exit 1
fi

#Check that the INSTALLNAME has been set
if [ ${#INSTALLNAME} -eq 0 ]; then
	echo  -e "ERROR: No configuration name given;  run again with ${YELLOW}sudo install.sh -i <configuration name> -m <module matrix>${NC}"
	exit 1
fi

#check that the MODULES has been set
if [ ${#MODULES} -eq 0 ]; then
	echo -e "ERROR: No modules have been specified;  run again with ${YELLOW}sudo install.sh -i <configuration name> -m <module matrix>${NC}"
	exit 1
fi

outputit "Start of nValuate Install Process"

ETCDIR="/etc/nvaluate"
DOCSTORE="/docstore/${INSTALLNAME}"
BACKUPDIR="${DOCSTORE}/backups"
DESTDIR="${APACHEROOT}/${INSTALLNAME}"
SENDGRDIDIR="${APACHEROOT}/SendGrid"
TEMPLATEDIR="/var/nvaluate/${INSTALLNAME}/templates"
SCRIPTDIR="/var/nvaluate/${INSTALLNAME}/scripts"
CRONFILE="${ETCDIR}/bin/Backup.sh"
DBNAME="${INSTALLNAME}"
HOSTNAME="${INSTALLNAME}.${ROOTDNSNAME}"
USERNAME='root'



outputit "INSTALLING"
outputit "APACHE WEBSERVER ROOT DIRECTORY: ${APACHEROOT}"
outputit "APACHE WEBSERVER DIRECTORY:      ${DESTDIR}"
outputit "BACKUP DIRECTORY:                ${BACKUPDIR}"
outputit "DATABASE NAME:                   ${DBNAME}"
outputit "HOST NAME:                       ${HOSTNAME}"
outputit "CRONFILE:                        ${CRONFILE}"
outputit "VAULT DIRECTORY:                 ${VAULTDIR}"
outputit "ADMINUSERNAME                    ${ADMINUSERNAME}"
outputit "ADMINPASSWORD                    ${ADMINPASSWORD}"
outputit "TIMEZONE                         ${TIMEZONE}"

if ! $NOUSERINPUT ; then
	echo -e "${GREEN}Press ENTER to continute of <ctrl c> to finish: ${NC}"
	read DUMMY
fi

#decomppres files
outputit "DECOMPRESSING FILES"
mkdir -p ${DIR}/tmpfiles
tar -C ${DIR}/tmpfiles -zxf ${DIR}/nvaluate-score.tar.gz
outputit "FILES DE-COMPRESSED"

#************************************************
#All checks of the intsall.conf file follow here:
#************************************************

if $INSTALLDATABASE ; then
	#Check if database already exists
	if [ -d /var/lib/mysql/${DBNAME} ] ; then 
		echo -n -e "${RED}The database ${YELLOW}${DBNAME} ${RED}already exists on this server"
		if $NOUSERINPUT ; then
			echo -e " install aborted${NC}"
			cleanupAll
			exit 1
		fi
		echo  -n -e ", do you want to override ${NC}[Y/N]" 
		read -e -p " " -i "N" YESNO
		if [ "$YESNO" != "Y" ]; then 
			cleanupAll
			exit 1
		else
			echo -n -e "${RED}***WARNING*** You are about to override and existing database, this will remove all data from it. Are you sure ${NC} [Y/N]"
			read -e -p " " -i "N" YESNO
			if [ "$YESNO" != "Y" ]; then  
				cleanupAll
				exit 1
			fi 
		fi
	fi
fi

outputit "Creating Directories"
rm -r $DESTDIR
mkdir -p $ETCDIR
mkdir -p $ETCDIR/bin
mkdir -p $ETCDIR/keys
mkdir -p $DESTDIR
mkdir -p $DESTDIR/reports
mkdir -p $TEMPLATEDIR
mkdir -p $SCRIPTDIR
chown www-data:www-data $DESTDIR/reports

mkdir -p /var/nvaluate
mkdir -p /var/nvaluate/$INSTALLNAME
mkdir -p /var/nvaluate/$INSTALLNAME/reports
mkdir -p /var/nvaluate/$INSTALLNAME/templates
mkdir -p /var/nvaluate/$INSTALLNAME/graphs
mkdir -p /var/nvaluate/$INSTALLNAME/scripts

chown www-data:www-data /var/nvaluate/$INSTALLNAME
chown www-data:www-data /var/nvaluate/$INSTALLNAME/reports
chown www-data:www-data /var/nvaluate/$INSTALLNAME/templates
chown www-data:www-data /var/nvaluate/$INSTALLNAME/graphs
chown www-data:www-data /var/nvaluate/$INSTALLNAME/scripts

#Create docstore
mkdir -p $DOCSTORE
chown www-data:www-data $DOCSTORE

#create  backup directory
mkdir -p $BACKUPDIR
chmod 777 $BACKUPDIR

#create dataroom
mkdir -p $DOCSTORE/dataroom
chown www-data:www-data $DOCSTORE/dataroom

#creeat scratch
mkdir -p $DOCSTORE/scratch

#create sendgrid
mkdir -p $SENDGRDIDIR

chmod 777 $BACKUPDIR

echo $VERSION > $DESTDIR/.version


outputit "Start of copy files"

outputit "Copy webfiles"
cp -a ${DIR}/tmpfiles/webfiles/. $DESTDIR/

outputit "Copy template files"
cp -a ${DIR}/tmpfiles/templates/. $TEMPLATEDIR/
chown -R www-data:www-data $TEMPLATEDIR

outputit "Copy script files"
cp -a ${DIR}/tmpfiles/scripts/. $SCRIPTDIR/
chown -R www-data:www-data $SCRIPTDIR

rm -r $DESTDIR/scripts
rm -r $DESTDIR/templates

if [ ${MODULES} -eq 1 ]; then
	cp -a ${DIR}/tmpfiles/score/. $DESTDIR/	
fi

if [ ${MODULES} -eq 2 ]; then
	cp -a ${DIR}/tmpfiles/room/. $DESTDIR/	
fi

if [ ${MODULES} -eq 3 ]; then
	cp -a ${DIR}/tmpfiles/score/. $DESTDIR/
	cp -a ${DIR}/tmpfiles/room/. $DESTDIR/	
fi

#install general nvaluate system files
cp ${DIR}/tmpfiles/system/EncryptBackup.php ${ETCDIR}/bin
cp ${DIR}/tmpfiles/system/LoadKeyVault.php ${ETCDIR}/bin
cp ${DIR}/tmpfiles/system/classVault.php ${ETCDIR}/bin
cp ${DIR}/tmpfiles/system/deleteVaultShelf.php ${ETCDIR}/bin
cp ${DIR}/tmpfiles/system/ResetAdminPassword.sh ${ETCDIR}/bin
cp ${DIR}/tmpfiles/system/RestoreBackup.php ${ETCDIR}/bin

chmod +x ${ETCDIR}/bin/ResetAdminPassword.sh


if $INSTALLDATABASE && $INSTALLWEBSITE ; then
	#Create uninstall file
	outputit "Creating unisntall file"
	sed -i "s:---INTALLATION_NAME---:${INSTALLNAME}:" ${DESTDIR}/uninstall-template.sh
	sed -i "s:---ROOTDNS---:${ROOTDNSNAME}:" ${DESTDIR}/uninstall-template.sh
	mkdir -p /etc/nvaluate/uninstall
	mv ${DESTDIR}/uninstall-template.sh /etc/nvaluate/uninstall/uninstall-${INSTALLNAME}.sh
	chmod +x /etc/nvaluate/uninstall/uninstall-${INSTALLNAME}.sh
	outputit "Unisntall file created"
fi

if [ -z "$TITLE" ] ; then
	if $INSTALLDATABASE ; then
		echo -e "${GREEN}Enter the title of the installation, this is the title set in the Globals:${NC}"
		read TITLE
	fi
fi

if $INSTALLKEYS ; then
	#create secure keys
	outputit "Create secure keys"
	chmod +x ${DESTDIR}/createKeys
	${DESTDIR}/createKeys -i ${INSTALLNAME} -m ${MODULES}
	if [ $? -ne 0 ]; then
		echo -e "${RED}Error creating new keys for vault${NC}"
		rm ${DESTDIR}/createKeys
		cleanupAll
		exit 1
	fi

	outputit "Load keys into vault"
	/etc/vault/newShelf -s ${INSTALLNAME} -m 314159
	if [ $? -ne 0 ]; then
		echo -e "${RED}Error creating new shelf and keys in vault${NC}"
		rm ${DESTDIR}/createKeys
		cleanupAll
		exit 1
	fi

	rm ${DESTDIR}/createKeys
	rm ${DESTDIR}/createVaultShelf.php

	#add aditional Keys
	vault add -s ${INSTALLNAME} -k LIMIT1 -v $LIMIT1
	vault add -s ${INSTALLNAME} -k LIMIT2 -v $LIMIT2
	vault add -s ${INSTALLNAME} -k LIMIT3 -v $LIMIT3
	
	#add siem host definition
	vault add -s ${INSTALLNAME} -k SIEMHOST -v siem.nvaluate.com


	#Getting Keys
	outputit "Getting Keys"
	PEPPER=$(/etc/vault/getKey -s $INSTALLNAME -k PEPPER)
	MYSQLUSERNAME=$(/etc/vault/getKey -s $INSTALLNAME -k DATABASE_USER)
	MYSQLPW=$(/etc/vault/getKey -s $INSTALLNAME -k DATABASE_PW)
	BACKUPCRYPT=$(/etc/vault/getKey -s $INSTALLNAME -k BACKUPKEY)
	ATTACHCRYPT=$(/etc/vault/getKey -s $INSTALLNAME -k ATTACHKEY)
	VERIFYKEY=$(/etc/vault/getKey -s $INSTALLNAME -k VERIFY_USER_KEY)

	#Checks
	if [[ -z $MYSQLUSERNAME ]] ; then
		echo -e "${RED}ERROR: Cannot find DATABASE_USER in Keys${NC}"
		exit 1
	fi

	if [[ -z $MYSQLPW ]] ; then
		echo -e "${RED}ERROR: Cannot find DATABASE_PW in Keys${NC}"
		exit 1
	fi
else
	rm ${DESTDIR}/createKeys
	rm ${DESTDIR}/createVaultShelf.php
fi

if $INSTALLDATABASE ; then
	#create database
	outputit "Creating Database"
	mysql -e "CREATE DATABASE IF NOT EXISTS ${DBNAME}"
	outputit "Create Database and user"
	mysql -e "DROP USER IF EXISTS '${MYSQLUSERNAME}'@'%'"
	mysql -e "CREATE USER '${MYSQLUSERNAME}'@'%' IDENTIFIED BY '${MYSQLPW}'"
	mysql -e "GRANT ALL ON ${DBNAME}.* TO '${MYSQLUSERNAME}'@'%'"

	outputit "Load Database Schema"
	mysql ${DBNAME} < ${DIR}/tmpfiles/sql/nVALUATE-Score.sql

	outputit "Insert global record into database"
	INSTANCEID="${TITLE}$RANDOM"
	mysql ${DBNAME} -e "INSERT INTO global (global_title,global_app_instance) VALUES ('${TITLE}',md5('${INSTANCEID}'))"

	#edit the database config file
	outputit "Edit database confg file"
	sed -i "s:--DIR--:${DESTDIR}:" ${DESTDIR}/config/parameters.php
	sed -i "s:--BACKUPS--:${BACKUPDIR}:" ${DESTDIR}/config/parameters.php

	#create default rolling
	outputit "Create defaults for rolling"
	mysql ${DBNAME} -e "INSERT into rolling (rolling_entity,rolling_modulus,rolling_target,rolling_idx,rolling_disable_seconds) VALUES ('verifyuser',10,0.2,0,3600)"
	mysql ${DBNAME} -e "INSERT into rolling (rolling_entity,rolling_modulus,rolling_target,rolling_idx,rolling_disable_seconds) VALUES ('score',10,0.2,0,3600)"
	mysql ${DBNAME} -e "INSERT into rolling (rolling_entity,rolling_modulus,rolling_target,rolling_idx,rolling_disable_seconds) VALUES ('comment',10,0.2,0,3600)"

	
	#create the control record
	mysql ${DBNAME} -e "INSERT into control (control_enabled,control_purchaser_name,control_purchaser_email,control_purchaser_company,control_status) VALUES (1,'${PURCHASENAME}','${ADMINUSERNAME}','${PURCHASECOMPANY}','active')"

	outputit "Admin Initial Username and Password set to ${ADMINUSERNAME}/${ADMINPASSWORD}"

	#create the first user
	outputit "Create first user"
	if  [[ -z $ADMINUSERNAME ]] ; then
		ADMINUSERNAME="admin"
	fi
	if  [[ -z $ADMINPASSWORD ]] ; then
		ADMINPASSWORD="admin"
	fi
	

	PEPPER=$(/etc/vault/getKey -s $INSTALLNAME -k PEPPER)
	
	#create the first user in the database
	outputit "Createing first database admin user"
	#create the salt and hash
	SALT="$(openssl rand -hex 32)"
	H1="$(echo -n "${SALT}${PEPPER}" | openssl dgst -sha256)"
	HASH1=${H1:$((${#H1} - 64)):64}
	H1="$(echo -n "admin${HASH1}" | openssl dgst -sha256)"
	HASH=${H1:$((${#H1} - 64)):64}

	outputit "Username and passwords have been created"

	mysql ${DBNAME} -e "INSERT into user (user_name,user_username,user_passwordhash,user_salt,user_security,user_forcereset,user_timezone) values ('Administrator','${ADMINUSERNAME}','${HASH}','${SALT}',251,1,'${TIMEZONE}')"

	#else
	#	php ${DESTDIR}/CreateFirstUser.php -i ${INSTALLNAME}
	#	rm ${DESTDIR}/CreateFirstUser.php

	if [ ${MODULES} -eq 2 -o ${MODULES} -eq 3 ]; then
		outputit "Creating dataroom"
		php ${DESTDIR}/CreateFirstRoom.php -i ${INSTALLNAME}
	fi
	
	
	rm ${DESTDIR}/CreateFirstRoom.php
else
	if [ -f "${DIR}/tmpfiles/sql/upgrade.sql" ] ; then
		echo "Upgrading database with new schema"
		mysql ${DBNAME} < ${DIR}/tmpfiles/sql/upgrade.sql
	fi
fi

if $INSTALLBACKUPS; then
	#create cd .. for cron
	outputit "Create cron backups"
	if [ ! -e $CRONFILE ]; then
		outputit "No cron file, so copying"
		mv ${DIR}/tmpfiles/system/Backup.sh $CRONFILE
		sudo chmod +x ${CRONFILE}
		rm ${DIR}/tmpfiles/system/Backup.sh
	else
		outputit "Found cron backup file"
	fi

	sed -i "s:\"---NEW---\":\"${INSTALLNAME}\" \"---NEW---\":" ${CRONFILE}
fi


if $INSTALLWEBSITE ; then
	#setup website
	#find apache location
	outputit "Setup apache site"
	APACHEDIR=""
	if [ -d "/etc/apache2" ]; then
		APACHEDIR="/etc/apache2"
	fi

echo "#### $HOSTNAME
<VirtualHost *:80>
ServerName $HOSTNAME
ServerAdmin webmaster@localhost
DocumentRoot $DESTDIR
<Directory $DESTDIR>
		Options FollowSymLinks
		AllowOverride All
		Require all granted
</Directory>
ErrorLog \${APACHE_LOG_DIR}/error.log
CustomLog \${APACHE_LOG_DIR}/access.log combined
Header always set Strict-Transport-Security \"max-age=63072000; includeSubdomains; preload\"
#Environment variables
SetEnv INSTALLATION_NAME ${INSTALLNAME}
SetEnv SENDGRID_API_KEY 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
SetEnv VAULTID 220759
SetEnv VAULT_SHELF ${INSTALLNAME}
#RewriteEngine on
#RewriteCond %{REQUEST_URI} !/controlApi.php$
#RewriteCond %{REQUEST_URI} !/NotEnabled.php$
#RewriteCond %{REQUEST_URI} !/images/NotEnabled.png$
#RewriteRule $ /NotEnabled.php?r=s [R=302,L] 
</VirtualHost>" > $APACHEDIR/sites-available/$HOSTNAME.conf

	#enbale new site
	outputit "Enable new website"
	a2ensite $HOSTNAME.conf

	#restart apache
	outputit "Restarting apache"
	systemctl reload apache2

	#get ssl cert
	if $SSL ; then
		#First checking that we have an IP address for the DNS name, we retry 10 times
		FOUNDIP=false
		IPADDR=""
		TRYING=true
		CNT=0
		while $TRYING  ; do
			IPADDR=$(dig +short ${HOSTNAME})
			if [ ${#IPADDR} -gt 0 ] ; then
				outputit "Found IPADDR for hostname ${HOSTNAME} of ${IPADDR}";
				FOUNDIP=true;
			fi
			((CNT++))
			if $FOUNDIP || [ $CNT -gt 10 ] ; then
				TRYING=false
			else
				outputit "Sleeping 60 seconds, waiting for DNS entry .....";
				sleep 60
			fi
		done
		if ! $FOUNDIP ; then
			outputit "Cannot find IP Address for ${HOSTNAME}"
			exit 31
		fi

		#Now we need to check that certbot runs, and retry if it fails
		CERTBOTOK=false
		CNT=0

		while [[ $CNT -lt 10 ]] ; do
			outputit "Attempting to run certbot"
			if certbot -n --apache -d $HOSTNAME --redirect > /dev/null 2>&1 ; then
				CERTBOTOK=true
				break
			fi
			((CNT++))
			outputit "Sleeping 60 seconds, waiting for certbot to work .....";
			sleep 60
		done

		if ! $CERTBOTOK ; then
			outputit "CERTBOT Failed for Aapache host ${HOSTNAME}"
			exit 33
		else
			outputit "CERTBOT Completed for ${HOSTNAME}"
		fi

		outputit "Restarting apache second time"
		systemctl reload apache2
	fi
fi

#Cleanup
outputit "Cleanup files"
cleanupAll

outputit "Install Complete"
exit 0