#!/usr/bin/bash

#
# This script will be called (as root) once at each zabbix-agent startup
#
# Call manually with "--force" to reset the password even if it's already set
#

export HOME=/root

FORCE=
if [ "$1" == "--force" ]; then
	FORCE="$1";
	shift;
fi

if mysqladmin ping >/dev/null 2>/dev/null; then

	# Configure the password if it hasn't been done yet
	# Note that the @localhost in the auth token is intentional
	if [ -f ~zabbix/.my.cnf ] && [ -n "$FORCE" ] || grep -qP '^\s*password\s*=\s*@PASSWORD@' ~zabbix/.my.cnf; then
		if [ -x /bin/ng-mk-auth-token ]; then
			NEWPASS=$(/bin/ng-mk-auth-token -f /etc/sysconfig/authseed mysql:zabbix_agent@localhost 24)
		else
			NEWPASS=$(dd if=/dev/urandom bs=1 count=24 status=noxfer 2>/dev/null | base64)
		fi
		# We aren't using augtool here (yet) because we still need to support el5 for now ;-(
		sed -i -re "s|@PASSWORD@|$NEWPASS|g" ~zabbix/.my.cnf
	fi

	# --show is needed to get the password rather than '********' since 5.6.25 (el7)
	# but it is unsupported and will cause an error on 5.0.x (el5)
	# A variable can be listed multiple times and the last one is the value actually used
	SHOW=$(my_print_defaults --help | grep -o -- --show)
	MYSQLUSER=$(  env HOME=~zabbix my_print_defaults "${SHOW}" mysql client | sed -nre 's/--user=//g p'     | tail -n 1)
	MYSQLPASSWD=$(env HOME=~zabbix my_print_defaults "${SHOW}" mysql client | sed -nre 's/--password=//g p' | tail -n 1)
	MYSQLHOST=$(  env HOME=~zabbix my_print_defaults "${SHOW}" mysql client | sed -nre 's/--host=//g p'     | tail -n 1)

	if [[ -z "$MYSQLHOST" ]]; then
		MYSQLHOST="localhost"
	fi

	# Account creation via grant is deprecated from 5.7.6 on so we do a CREATE + GRANT instead
	# but the IF NOT EXISTS option for CREATE USER isn't available in MySQL 5.0.x
	# Reset the global (*.*) privileges and password.  We do all these seperately so that
	# individual statements can failed (eg the REVOKE will fail is this is our first run)
	mysql -e "REVOKE ALL PRIVILEGES ON *.* FROM $MYSQLUSER@${MYSQLHOST};" 2>/dev/null
	mysql -e "CREATE USER ${MYSQLUSER}@${MYSQLHOST} IDENTIFIED BY '$MYSQLPASSWD';" 2>/dev/null
	# CREATE USER may fail (eg if the user already exists) so we also set the password explictly
	mysql -e "SET PASSWORD FOR USER $MYSQLUSER@${MYSQLHOST} = '$MYSQLPASSWD';" 2>/dev/null
	mysql -e "GRANT SHOW DATABASES, PROCESS, REPLICATION CLIENT ON *.* TO $MYSQLUSER@${MYSQLHOST};" 2>/dev/null

	if mysql -NB -e 'DESC ocacommon.billingsnapshot' >/dev/null 2>&1; then
		# Grant access to the oca billing metrics if they exist
		mysql -e "GRANT SELECT ON ocacommon.billingsnapshot TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
	fi

	if mysql -NB -e 'DESC ocacommon.zabbixmetric' >/dev/null 2>&1; then
		# Grant access to the oca billing metrics if they exist
		mysql -e "GRANT SELECT ON ocacommon.zabbixmetric TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
		mysql -e "GRANT SELECT ON ocacommon.zabbixmetriclog TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
		mysql -e "GRANT SELECT ON ocacommon.zabbixmetriclogdatapoint TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
	fi

	if mysql -NB -e 'DESC ocacommon.ocaqueuestatistics' >/dev/null 2>&1; then
		# Grant access to the oca statistics if it exists - issue #50839
		mysql -e "GRANT SELECT ON ocacommon.ocaqueuestatistics TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
	fi

	if mysql -NB -e 'DESC ocacommon.ocaqueue_delay' >/dev/null 2>&1; then
		# Grant access to ocaqueue delay stats if it exists - INFRA-1929
		mysql -e "GRANT SELECT ON ocacommon.ocaqueue_delay TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
	fi

	if mysql -NB -e 'DESC ocacommon.bulkgeocodelog' >/dev/null 2>&1; then
		# Grant access to the oca bulkgeocodelog if it exists - issue #50978
		mysql -e "GRANT SELECT ON ocacommon.bulkgeocodelog TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
	fi

	if mysql -NB -e 'DESC performance_schema.threads' >/dev/null 2>&1; then
		# Grant access to the performance_schema threads table if it exists - INFRA-718
		mysql -e "GRANT SELECT ON performance_schema.threads TO $MYSQLUSER@${MYSQLHOST}" >/dev/null
	fi

	### INFRA-1849 OCAv1 Certificate monitoring
	# Note that the certificates table *DOES* contain prviate keys, but they are encrypted so
	# Allowing Zabbix unfilter (read) access to them should be relatively safe.
	#
	# Unfortunantly you can't grant table level privileges on a database pattern in MySQL
	# so we need to set up a scheduled event to create the appropriate privileges for each
	# database that exists
	#
	# TODO: Can/should we clean up old GRANTS we added too, does MySQL clean on DROP?
	# NOTE: This requires that the event scheduler is enabled in mysql (event_scheduler = ON)
	#
	mysql -NB -e 'CREATE DATABASE IF NOT EXISTS zabbix_agent';
	mysql -NB --database zabbix_agent <<-EOD

		DROP EVENT IF EXISTS UPDATE_ZABBIX_AGENT_GRANTS;

		DELIMITER //

		CREATE EVENT IF NOT EXISTS UPDATE_ZABBIX_AGENT_GRANTS
		    -- Every hour, but for the first one to be 10 seconds from now
		    ON SCHEDULE EVERY 1 HOUR STARTS CURRENT_TIMESTAMP - INTERVAL 59 MINUTE - INTERVAL 50 SECOND
		    DO BEGIN
		        -- Generate the required tables_priv entries from INFORMATION_SCHEMA.TABLES
		        REPLACE INTO mysql.tables_priv (Host, Db, User, Table_name, Grantor, Timestamp, Table_priv, Column_priv)
		         SELECT '${MYSQLHOST}' AS Host,
		                 TABLE_SCHEMA,
		                 '${MYSQLUSER}' AS User,
		                 TABLE_NAME,
		                 USER() AS Grantor,
		                 '0000-00-00 00:00:00' AS 'Timestamp',
		                'Select' AS Table_priv,
		                '' AS Column_priv
		           FROM INFORMATION_SCHEMA.TABLES
		          WHERE TABLE_SCHEMA LIKE 'oca\_%' AND TABLE_NAME='certificates'
		          ORDER BY TABLE_SCHEMA ASC;

		        -- Because we message with the privilege tables manually we need a FLUSH
		        FLUSH PRIVILEGES;
		    END
		//

		DELIMITER ;
	EOD

fi
