#!/bin/bash


##  Installs mntos 
##
##  Original version worked, but hard-wired
##
##  Changed in version 1.0.4.1--7:  (ggonzalez@nagios.com)
#
#	General refactoring
#	Added many variables set at the top for customization
#	changed the Python progfram to accept the version number
#	Added quite a bit more error checking
#

##  Changed in version 1.0.4.8:  (ggonzalez@nagios.com)

#	Ran through ShellCheck, fixed many errors and infelicities

##  Changed in version 1.0.4.9:  (ggonzalez@nagios.com)
#	Added "Good" progress messages
#	Added checking for chown failures
#
 
##  Changed in version 1.0.4.10:  (ggonzalez@nagios.com)
#	Added Ubuntu support
#	Added apachectl2 support.
#	More checking for command failures
#	Added apache connect test.
 
  
##  Changed in version 1.0.4.11:  (ggonzalez@nagios.com)
#   quoted all vars

##  Changed in version 1.0.4.12:  (ggonzalez@nagios.com)
#   Fixed even more problems with finding our IP address and port.

##  Changed in version 1.0.4.13:  (ggonzalez@nagios.com)
#   Added checks for time zone being set in PHP

##  Changed in version 1.0.4.14:  (ggonzalez@nagios.com)
#   Quite a few adjustments to also work on Ubuntu

##  Changed in version 1.0.4.15:  (ggonzalez@nagios.com)
#   Quite a few more adjustments to also work on Ubuntu
#   Checks for Ubuntu version > 14 as it needs php 7.0
#   Guards service restart for iptables.

##  Changed in version 1.0.4.16:  (ggonzalez@nagios.com)
##	More changes for Ubuntu install of apache php modules
##	Works correctly whether firewalld is running or not.

##  Changed in version 1.0.4.17:  (ggonzalez@nagios.com)
#
#	Completely rewrote the PHP/Apache installer
#	Bulletproofed the iptables steps some more
#	Now we test the php and apache installations round-trip.


Version=1.0.4
ScriptRevision=17
mntosName=mntos-"$Version"
TarFile="$mntosName".tar.gz
Base=/opt
MntosDir="$Base/$mntosName"
ConfFile="$MntosDir/config.ini"
NagiosxiDownloads=https://assets.nagios.com/downloads/nagiosxi
ConfProg=NagiosXI-MNTOS-configure.py
DesiredOwner=nagios
TestArchive=/tmp/"$mntosName".tar.gz
DownloadPlace="https://assets.nagios.com/downloads/exchange/mntos/mntos-1.0.4.tar.gz"
WebServerPort=80
ThisMachineName=$( hostname )
ThisMachineFQDN=$( domainname )
ThisMachineFullInfo="$ThisMachineName  ($ThisMachineFQDN)"
Warnings=""
Notes=""
GoodMessages=""

set -u	## bomb out on undef vars
set -e	## bomb out on errors right away


function Exists( ){
	Prog="$1"
	if which "$Prog" 1>/dev/null 2>/dev/null  ; then
		#echo "program [$Prog] exists!!"
		return 0
	else
		#echo "program [$Prog] does not exist!!"
		return 1
	fi
}


function Echo( ) {
        echo -e "$@"
}


function Divider() {
		Echo "\n\n--------------------------------------------------------------------"

}


function ShowErrs( ) {
echo ""
	if [ "$Warnings" != "" ]; then
		Divider
		Echo "*** Look over these warnings:\n$Warnings\n\n"
	fi

	if [ "$Notes" != "" ]; then
		Divider
		Echo "*** Look over these notes:\n$Notes\n\n"
	fi
	if [ "$GoodMessages" != "" ]; then
		Divider
		Echo "*** Look over these notices of proper installation:\n$GoodMessages\n\n"
	fi
	Divider
}



function Fatal( ) {
	ExitCode="$1"
	ShowErrs
	Echo "\n\n!!! >>>>>>>>>>> Fatal error: $2  !!!!!! <<<<<<<<<\n\n"
	exit "$ExitCode"
}



function Warning( ) {
	Echo "\n!!!!!! >>>>>>>  Warning: $1  !!! <<<<<<< continuing.\n"
	Warnings="$Warnings"'\n'"$1"
}


function Note( ) {
	ExitCode="$1"
	Echo "!!! >>>> Note: $1  <<<<"
	Notes="$Notes"'\n'"$1"
}


function Good( ) {
	Echo "Good Progress: $1"
	GoodMessages="$GoodMessages"'\n'"$1"
}


function CheckRoot( ) {
	if [ "$(whoami)" != "root" ]; then
		Fatal  1 "This script needs to be run as root/superuser."
	fi
}


TheGroup=""
AllProbedGroups=""

function ProbeGroup( ){
	AllProbedGroups="$AllProbedGroups""   ""$1"
	if Exists 'getent'; then
		if getent group "$1"   1>/dev/null  2>/dev/null; then
		        TheGroup="$1"
	        fi
	else
		if grep -w "^$1" /etc/group   1>/dev/null  2>/dev/null; then
		        TheGroup="$1"
	        fi
	fi

	}


function ChangeOwnerAndGroup( ){
	ThisDir=$( pwd )
	if chown -R "$DesiredOwner:$TheGroup" 	"$ThisDir"; then
		Good "Correctly changed ownership of [$ThisDir] to [$DesiredOwner:$TheGroup]"
	else
		Fatal 2 "Cannot chown directory [$ThisDir] to [$DesiredOwner:$TheGroup] !!!"
	fi
}


function chmodX( ){
     if chmod "$@"; then
        Good "File ownership changed okay."
     else
        Echo "$@"
        Fatal 33 "The chmod command failed on [$*] !"
     fi
}


function ChangeModes( ){
	chmodX o-r 	"networks.ini"
	chmodX g+w 	"."
}


function sub( ) {
	Fn="$2"
	if ! sed --in-place "s;$1\=.*;$1=$Fn;" 		"$ConfFile"; then
		Warning "Unable to change $2 in $MntosDir"
	fi
}


function GetOSInfo( ) {
   if Exists 'lsb_release'; then
        SystemFlavor=$( lsb_release -si )
        SystemVersion="$(   lsb_release -sr | cut -d '.' -f 1 )"
   else  ## if no lsb_release
        if [ -f /etc/redhat-release ]; then
                if rpm -q centos-release ; then
                        SystemFlavor='CentOS'
                else
                        if rpm -q redhat-release || rpm -q redhat-release-server ; then
				SystemFlavor=RedHatEnterpriseServer
			else
				SystemFlavor=''
				Warning "System version not found."
			fi
		fi     ##>/dev/null
		SystemVersion="$( sed 's/.*release \([0-9.]\+\).*/\1/' /etc/redhat-release | cut -d '.' -f 1   )"
        else
                Warning "Not a redhat or lbs release"
		SystemFlavor=''
	fi  ## redhat-release
   fi  ## lsb_release

	if [ "$SystemFlavor" = '' ]; then
		Warning "Unable to determine what Linux SystemFlavor we are running on!!"
		Warning "Proceeding on a best guess on what programs are available."
	else
	   	Good "We determined we are running on system [$SystemFlavor] version [$SystemVersion]\n"
	fi
}


function DoubleCheck( ) {
	if cd "$MntosDir" ; then
		Good "Found correct directory in tar file"
	else
		Warning "OOPS, did not get expected directory from tar file!!, expected [$MntosDir], found:"
		ls -l
		if cd	"$Base/mntos-*" ; then
			MntosDir="$( pwd )"
			Warning "Proceeding instead in $MntosDir"
		else
			Fatal 5 "No untarred mntos directory found!"
		fi
	fi
}


function ChangeConfig( ) {
	if sub contacts  "$MntosDir/" && sub networks   "$MntosDir/"  && sub xmloutput  "$MntosDir/www/"; then
		Good "Modified mntos config file [$ConfFile] okay!"
	else
		Warning "Errors in modifying config file [$ConfFile]!!"
	fi
}

function DownLoadTar( ) {
	if wget -q "$DownloadPlace" -O "$TarFile"; then
		Good "Download of [$DownloadPlace] okay!!"
	else
		Fatal 3 "Unable to download [$DownloadPlace]  !!!"
fi
}


function UseTestArchive( ){
		cp "$TestArchive" "$TarFile"
		Warning ">>>Note well:\n\nWe are using test archive in [$TestArchive] instead of http download from [$DownloadPlace]"
}


function FixWWWPerms( ){
	pushd  /opt
		chmod 755 "$mntosName"

		cd "$mntosName" &&  chmod 644 ./* && 	chmod 755 www
		cd www          && chmod 644 ./*  &&	chmod 755 img
		cd img          && chmod 644 ./*  &&    chmod 755 default
		cd default      && chmod 644 ./*
	popd
}


function GetOtherFiles( ){
	GURL=$NagiosxiDownloads/misc/globe.png
	if [ -d www ]; then  ## correct tar happened
		if ! wget -q	"$GURL" -O www/img/globe.png; then
			Warning "Did not get the globe: [$GURL]"
		fi
		FixWWWPerms
		if [ ! -f "$ConfProg" ]; then
			wget -q	"$NagiosxiDownloads/scripts/$ConfProg"  ## if not in the mntos gz file...
		fi
	else
		Fatal 66 "bad tar file?"
	fi
}


function GetFiles( ) {
# Download and install MNTOS from Exchange
	Echo "\nGetting mntos files...."
	if cd "$Base"; then
		if [ -f "$TestArchive" ]; then
			UseTestArchive
		else
			DownLoadTar		
		fi
		if tar zxf "$TarFile"; then
			Good "Untarred distribution file [$TarFile]"
			
			rm "$TarFile"
			DoubleCheck
			GetOtherFiles
		else
			Fatal 27 "Untar of [$TarFile] failed!!"
		fi
		ChangeConfig
	else
		Fatal 22 "Cannot change to directory [$Base]  !!"
	fi
}


function EnsureHaveUser( ) {
	if  id -u "$DesiredOwner"   1>/dev/null  2>/dev/null  ; then
		Good	"Found user [$DesiredOwner], okay."
	else
		Note "Cannot find a user [$DesiredOwner] on $ThisMachineFullInfo !!!   Adding them"
		if useradd "$DesiredOwner" ; then
			Good "Successfully added user [$DesiredOwner] to [$ThisMachineFullInfo]  ."
		else
			Fatal 6 "Cannot add user [$DesiredOwner]  to $ThisMachineFullInfo !!! They are needed as the user to run a cron job as."
		fi
	fi

}



function RestartApache( ) {
	Echo "Now restarting Apache..."
	if Exists 'apache2ctl' ; then
		if apache2ctl  restart ; then
			Good "Apache web server restarted."
		else
			Warning "apache2ctl command exists but apache2ctl restart failed"
		fi
	else
		if Exists 'service' ; then
			if service httpd restart ; then
				Good "Apache web server restarted."
			else
				Warning "service command exists but service httpd restart failed"
			fi
		else
			if Exists 'systemctl' ; then
				if systemctl start httpd ; then
					Good "Apache restarted.":
				else
					Fatal 9 "Cannot restart web server with systemctl start httpd]!!"
				fi
			else
				Warning "Unable to restart apache as apache2ctl nor service nor systemctl found"
			fi
		fi
	fi
	if /sbin/chkconfig --levels 235 httpd on ; then
		Good "Apache set to restart on boot."
	fi
}


function AddHostCentosOlder( ){
    cat > /etc/httpd/conf.d/mntos.conf  <<//HERE//
	Alias /mntos "$MntosDir/www"

	<Directory "$MntosDir/www">
	#  SSLRequireSSL
	   Options 		None
	   AllowOverride 	None
	   Order 		allow,deny
	   Allow 		from all
	</Directory> 
//HERE//

}


function SetPHP_TimeZone( ){
	if [ -f /etc/timezone ]; then
	  OLSONTZ="$( cat /etc/timezone )"
	elif [ -h /etc/localtime ]; then
	  OLSONTZ="$( readlink /etc/localtime | sed "s/\/usr\/share\/zoneinfo\///" )"
	else
	  checksum="$( md5sum /etc/localtime | cut -d' ' -f1 )"
	  OLSONTZ="$( find /usr/share/zoneinfo/ -type f -exec md5sum {} \; | grep "^$checksum" | sed "s/.*\/usr\/share\/zoneinfo\///" | head -n 1 )"
	fi
	PHP_IniFile=/etc/php.ini
	TZCOMMAND='date.timezone = "'$OLSONTZ'"'  
	echo "Time zone is [$OLSONTZ]  the command line for PHP.ini is [$TZCOMMAND]"
	if [ -f "$PHP_IniFile" ]; then
		sed --in-place  '/date\.timezone =/d' "$PHP_IniFile"
		echo "$TZCOMMAND" >>"$PHP_IniFile"
	else
		echo "$TZCOMMAND" >"$PHP_IniFile"
	fi
}


function AptGetUpdate(){
		if Exists 'apt-get'; then
			if apt-get 	update; then
				Good "good apt-get update"
			else
				Warning "could not do an apt-get update"
			fi
		fi
}


UAlways="apt-get -y install apache2"

Ubuntu_14="$UAlways libapache2-mod-php5 php5 php5-mcrypt php5-xsl"
Ubuntu_15=$Ubuntu_14
Ubuntu_16="$UAlways libapache2-mod-php php7.0-xml php7.0 php-mcrypt php7.0-curl php7.0-json php7.0-cgi"

CentOS_6="yum -y install httpd wget php php-xml php-fpm"
CentOS_7=$CentOS_6

Ubuntu_14_Restart="service apache2 restart"
Ubuntu_15_Restart="systemctl restart apache2"
Ubuntu_16_Restart=$Ubuntu_15_Restart


function TestPHP(){
	echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php
	if curl "http://localhost/info.php"  | grep 'Virtual Directory Support'; then
		Echo "PHP seems to be installed okay!!"
	else
		Warning "PHP test failed!!"
	fi 
}


function InstallPHP(){
	Always="   "
	RightCommandVarName=${SystemFlavor}_${SystemVersion}
	if eval RightCommand="\$$RightCommandVarName"; then
		Echo "Found the right modules for $SystemFlavor $SystemVersion"
	else
		Echo "Cant find the right modules for $SystemFlavor $SystemVersion"
		exit 66
	fi
	Echo "The proper command is [$RightCommand]"
	if $RightCommand; then
		Good "PHP installed okay, now testing....!!"
		TestPHP
	else
		Fatal 44 "PHP did not install correctly???, command was $RightCommand"
	fi
}


function TestApache(){
	if Exists apache2ctl; then
		if apache2ctl configtest; then
			Good "Apache configtest seems okay"
		else
			Warning "Apache test not quite right??"
		fi
	fi
}
				
			
function InstallThingsNeeded( ){
		AptGetUpdate
		InstallPHP	
		TestApache
 	    SetPHP_TimeZone
        Good  "Prerequisites installed okay!"
}


function SetDirectivesForApache( ) {
	NewModule=mod_authz_core.c
	DFN="$1"
    	cat >"$DFN" <<//HERE//

Alias /mntos "$MntosDir/www"

<Directory "$MntosDir/www">

     <IfModule $NewModule>   
						# httpd 2.4
             Require all granted
     </IfModule>

     <IfModule !$NewModule>  
						# httpd 2.2
             Order deny,allow
             Deny from all
             Allow from all
     </IfModule>

</Directory>

//HERE//
        ExitCode=$?
	if [ "$ExitCode" -eq 0 ] && [ -f "$DFN" ]; then
		Good "Created Apache config file at [$DFN]"
	else
		Warning "Unable to create Apache config file at [$DFN]"
	fi
}


function AddHostDefinition( ) {
	DFN=mntos.conf
	DirectiveDirHttpd=/etc/httpd
	ApacheSites=/etc/apache2/sites-available

	if [ -d "$DirectiveDirHttpd" ]; then
		DirectiveFnHttpd=conf.d/"$DFN"
		DirectivePathHttpd="$DirectiveDirHttpd/$DirectiveFnHttpd"
		SetDirectivesForApache "$DirectivePathHttpd"
	else
		if [ -d "$ApacheSites" ]; then
			ApacheFn="$ApacheSites/$DFN"
			SetDirectivesForApache "$ApacheFn"
			a2ensite mntos
			service apache2 reload
		else
			Warning "Neither home of apache directives found!!!"
		fi
	fi

# Reload Apache configuration
    RestartApache
}


function SetupAccessToAllowConnectionsToApacheWebServer( ) {
	Echo "\n\n"
	if Exists 'firewall-cmd' ; then
		echo "Now updating firewall-cmds to allow connections to this web serve $ThisMachineFullInfo  ..." 
		if systemctl status firewalld | grep 'running'; then
			firewall-cmd --zone=public --add-port="$WebServerPort"/tcp
			firewall-cmd --reload
			Good "Changed rules for firewallD to allow web connections"
		else
			Warning  "FirewallD not running, options not changed"
		fi
	else
		if Exists 'iptables'; then
			IPTABOPTS=" -I INPUT    -m state    --state NEW    -m tcp    -p tcp"
			echo "Now updating iptables to allow connections to this web server  $ThisMachineFullInfo  ..."
			if iptables   $IPTABOPTS    --dport "$WebServerPort"    -j ACCEPT; then
				Note "IpTables accepted port opening request."
				if service iptables save; then	     ## save in-mem config to startup config file
					Note "Iptables updated to these changes after restart"
				else
					Warning "IpTables save did not work, trying alternate"
					if iptables-save; then
						Good "Alternate iptables-save script worked!"
					else
						Warning "Alternate iptables-save script did not work."
					fi
				fi
			else
				Warning "Iptables did not accept port request."
			fi
		else
			if Exists 'ufw'; then
				ufw allow 80/tcp
			else
				Warning "Cannot find iptables or firewall-cmd or ufw, cannot set open web server port!!"
			fi
		fi
	fi
	echo ""
}


function AdjFiles( ) {
	TheGroup=""
	AllProbedGroups=""
	ProbeGroup  www-data 
	ProbeGroup  apache
	if [ "$TheGroup" != "" ]; then
		ChangeOwnerAndGroup
	else
		Fatal 8 "None of the groups in the list [ $AllProbedGroups ] that apache creates found!!"
	fi
	ChangeModes
}


function DoConfigging( ) {
	Echo "\n\nNow enter some mntos configuration information please\n"
	python "$ConfProg"	-v "$Version"	# Walk through initial setup to show in the interface
	rm -f "$ConfProg"
}

FirstPart='* * * * *'
LastPart="	/usr/bin/php   $MntosDir/mntos.php     1>/dev/null 2>/dev/null"


function MakeCrondJobForMntos( ) {
	CronLine="$FirstPart   $DesiredOwner  $LastPart"
	echo "$CronLine" >/etc/cron.d/mntos
}


function BothCronJobs( ){
	CronLine="$FirstPart"" $LastPart"
	Place=/var/spool/cron/crontabs
	CronUser=root
	CronFile="$Place/$CronUser"
	if [ -d "$Place" ]; then
		Note "Creating Ubuntu-like cron job."
		echo "$CronLine" 	>	"$CronFile"
		chown "$CronUser:$CronUser" 	"$CronFile"
		chmod 600  			"$CronFile"
		if crontab -l | grep 'mntos'; then
			Good "Cron job seems to be created okay."
		else
			Warning "Cron job not made ???"
		fi
	else
		Note "Creating cron.d type of cron job."
		MakeCrondJobForMntos
	fi
}
		

function NewGetWebServerPortWithNetstat( ) {
 	InfoLine=$( netstat --listening --program --extend --numeric-ports | grep --perl-regexp '/httpd|/apache' )
	if [ "$InfoLine" = '' ]; then
		Warning "Did not see any http servers from netstat??"
		Ipa=""
		Prt=""
	else
		SetCmds="$( echo \\"$InfoLine\\"  |  awk '{ print $4 }' | sed -e 's;\[::\];\*;' -e 's;:::;\*:;'   -e 's;0\.0\.0\.0:;\*:;' )"
		IFS=':' read -r -a Info <<< "$SetCmds"
		echo "Setcmds = [$SetCmds]"
		Ipa="${Info[0]}"
		Prt="${Info[1]}"
			#echo "The web server IP address is [$Ipa]"
			#echo "The web server IP port is [$Prt]"

		if [ "$Ipa" != ""  ]  && [ "$Prt" != "" ]; then
			DefaultIPRouteLine="$( ip route | grep 'src' )"
			if [ "$Ipa" = '*' ]; then
				#echo "Outgoing route line=[$DefaultIPRouteLine]" 
				Ipa=$( echo "$DefaultIPRouteLine" | grep  -E -o 'src [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'    | awk '{ print $NF;exit 0;}' )
				#echo "IP Out = [$Ipa]   from  [$DefaultIPRouteLine]"	
			else
				Ipa="$Ipa"
			fi
			echo "The web server IP address is [$Ipa]"
			echo "The web server IP port is [$Prt]"
			Good	"Found our apache web server with netstat"
		else
			Warning "Did not get server IP address or port info"
			Warning "netstat said: [$InfoLine]"
		fi
	fi
}


function NewGetWebServerPortWithIp( ) {
	Ipa=$(ip addr | grep global | grep -m 1 'inet' | awk '/inet[^6]/{print substr($2,0)}' | sed 's|/.*||')
	Prt='80'
}


function NewGetWebServerPort( ) {
	Ipa=""
	Prt=""
	if Exists 'netstat'; then
		NewGetWebServerPortWithNetstat
	else
		if Exists 'ip'; then
			NewGetWebServerPortWithIp
		else
			Warning "Cannot get web server info with either netstat or ip??"
		fi
	fi
}


function CheckConnection (){
	if [ "$OurURL" = "" ]; then
		Warning "We have not been able to discern a URL for our apache server so we cannot test it."
	else
		if curl "$OurURL"  -s -f -o /dev/null; then
	 		Good    "Website [$OurURL] up." 
		else
		 	Warning "Website [$OurURL] down."
		fi
	fi
}


function FinishUp( ) {
	#Conf=$( ifconfig )
	#Addr=$( echo "$Conf" | grep "inet\ addr" | head -n1 | sed -e 's/^[^:]*://'    -e 's/\ .*//' )
	#echo "ADDR=[$Addr]"
	#exit 99
	NewGetWebServerPort
	if [ "$Ipa" = "" ]; then
		OurURL=""
	else	
		if [ "$Prt" = '80' ]; then
			Addr="$Ipa"
		else
			Addr="$Ipa:$Prt"
		fi
		OurURL="http://$Addr/mntos/"
	fi

	CheckConnection
	Good "============================="
	Good "MNTOS Installation Complete!"
	if [ "$OurURL" != "" ]; then
		Good "You can now view the MNTOS interface at:   $OurURL"
	else
		Warning "Sorry, we could not find a listening web server"
	fi
	Good "============================="
	ShowErrs
}


function AdjustRefresh( ){
	# This line is here so it can be changed if the job is changed to run less than every minute (it's in seconds)
	sed -i 's/refreshfreq \= 60/refreshfreq = 60/' www/index.php
}


function MainCode( ) {
	Echo "\n\nInstall script for mntos\n8-Feb-2017  mntos version $Version    (Script revision $ScriptRevision)\n"

	CheckRoot		# Check whether we have sufficient privileges
	GetOSInfo
	EnsureHaveUser
	InstallThingsNeeded
	GetFiles	
	DoConfigging
	SetupAccessToAllowConnectionsToApacheWebServer
	BothCronJobs
	AdjustRefresh
	AdjFiles		# Adjust permissions
	AddHostDefinition	# Create a virtual host definition for Apache
	FinishUp
}



#--------------------------------------  main code starts here


MainCode



