First commit to own repository

This commit is contained in:
Jörg Deckert 2023-10-15 11:06:01 +02:00
parent 976d73d255
commit 98d73c43e9
24 changed files with 1766 additions and 0 deletions

145
Makefile Normal file
View File

@ -0,0 +1,145 @@
02firstboot = $(CHROOT)/usr/local/bin/02firstboot.start
cert-renew.sh = $(CHROOT)/etc/ssl/cert-renew.sh
zabbix-userparameter = $(CHROOT)/var/lib/zabbix/userparameter_mysql.conf
systemd-units: appliance/MySQL-Backup.sh appliance/backup.service appliance/backup.timer appliance/cert-renew.service appliance/cert-renew.timer
mkdir -p $(CHROOT)/usr/local/bin
cp appliance/MySQL-Backup.sh $(CHROOT)/usr/local/bin/
cp appliance/backup.service appliance/backup.timer appliance/cert-renew.service appliance/cert-renew.timer $(CHROOT)/etc/systemd/system/
$(02firstboot): appliance/02firstboot.start
mkdir -p $(CHROOT)/usr/local/bin
cp $< $@
touch $(CHROOT)/02firstboot
$(cert-renew.sh): appliance/cert-renew.sh
mkdir -p $(CHROOT)/etc/ssl
cp $< $@
$(CHROOT)/var/lib/mysql: mariadb/my.cnf.root
# MariaDB-Konfiguration ($$, weil make ein $ entfernt)
sed -i "s/^character-set-server.*$$/character-set-server = utf8mb4/" $(CHROOT)/etc/mysql/mariadb.d/50-distro-server.cnf
sed -iE 's/^\(log-bin\)/#\1/' $(CHROOT)/etc/mysql/mariadb.d/50-distro-server.cnf
echo >> $(CHROOT)/etc/mysql/mariadb.d/50-distro-server.cnf
echo "# innodb tuning" >> $(CHROOT)/etc/mysql/mariadb.d/50-distro-server.cnf
echo "innodb_buffer_pool_size = 2G" >> $(CHROOT)/etc/mysql/mariadb.d/50-distro-server.cnf
echo "innodb_strict_mode = OFF" >> $(CHROOT)/etc/mysql/mariadb.d/50-distro-server.cnf
cp mariadb/my.cnf.root $(CHROOT)/root/.my.cnf
chmod 0600 $(CHROOT)/root/.my.cnf
rm -rf $(CHROOT)/var/lib/mysql/*
RUN bash -c 'yes gentoo | emerge --config dev-db/mariadb'
apache-php:
sed -i 's:APACHE2_OPTS=\":APACHE2_OPTS=\"-D PHP :' $(CHROOT)/etc/conf.d/apache2
find $(CHROOT)/etc/php/apache2-*/ -iname php.ini -print | xargs \sed -i \
-e 's:.*date.timezone =.*:date.timezone = Europe/Berlin:' \
-e 's:.*pcre.jit=.*:pcre.jit=0:' \
-e 's:.*max_execution_time =.*:max_execution_time = 300:' \
-e 's:.*max_input_time =.*:max_input_time = 300:' \
-e 's:.*post_max_size =.*:post_max_size = 16M:' \
-e 's:.*always_populate_raw_post_data =.*:always_populate_raw_post_data = -1:'
zabbix-services:
echo "zabbix-agent 10050/tcp Zabbix Agent" >> $(CHROOT)/etc/services
echo "zabbix-agent 10050/udp Zabbix Agent" >> $(CHROOT)/etc/services
echo "zabbix-trapper 10051/tcp Zabbix Trapper" >> $(CHROOT)/etc/services
echo "zabbix-trapper 10051/udp Zabbix Trapper" >> $(CHROOT)/etc/services
zabbix-webapp:
RUN webapp-config -h localhost -d zabbix -I zabbix `ls $(CHROOT)/usr/share/webapps/zabbix`
cp $(CHROOT)/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php.example $(CHROOT)/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php
# enable any language
sed -i "s:'display' => false]:'display' => true]:" $(CHROOT)/var/www/localhost/htdocs/zabbix/include/locales.inc.php
# im Zabbix-Ebuild wird fowners und fperms vor webapp_src_install aufgerufen und deswegen wieder überschrieben
RUN chown -R zabbix:zabbix \
/etc/zabbix \
/var/lib/zabbix \
/var/lib/zabbix/home \
/var/lib/zabbix/scripts \
/var/lib/zabbix/alertscripts \
/var/lib/zabbix/externalscripts \
/var/log/zabbix
chmod 0750 \
$(CHROOT)/etc/zabbix \
$(CHROOT)/var/lib/zabbix \
$(CHROOT)/var/lib/zabbix/home \
$(CHROOT)/var/lib/zabbix/scripts \
$(CHROOT)/var/lib/zabbix/alertscripts \
$(CHROOT)/var/lib/zabbix/externalscripts \
$(CHROOT)/var/log/zabbix
$(zabbix-userparameter): zabbix/userparameter_mysql.conf
mkdir -p $(CHROOT)/var/lib/zabbix
cp $< $@
zabbix-syslog:
# Zabbix Syslog (https://github.com/v-zhuravlev/zabbix-syslog)
mkdir -p $(CHROOT)/etc/zabbix/scripts/lib
cp zabbix/zabbix-syslog/zabbix_syslog_create_urls.pl $(CHROOT)/etc/zabbix/scripts/zabbix_syslog_create_urls.pl
cp zabbix/zabbix-syslog/zabbix_syslog_lkp_host.pl $(CHROOT)/etc/zabbix/scripts/zabbix_syslog_lkp_host.pl
cp zabbix/zabbix-syslog/Template_syslog.xml $(CHROOT)/etc/zabbix/scripts/Template_syslog.xml
cp zabbix/zabbix-syslog/zabbix_syslog.cfg $(CHROOT)/etc/zabbix/zabbix_syslog.cfg
cp zabbix/zabbix-syslog/lib/ZabbixAPI.pm $(CHROOT)/etc/zabbix/scripts/lib/ZabbixAPI.pm
cp zabbix/zabbix-syslog/70-zabbix_rsyslog.conf $(CHROOT)/etc/rsyslog.d/70-zabbix_rsyslog.conf
RUN chown -R zabbix:zabbix /etc/zabbix/scripts
chmod +x $(CHROOT)/etc/zabbix/scripts/zabbix_syslog_create_urls.pl
chmod +x $(CHROOT)/etc/zabbix/scripts/zabbix_syslog_lkp_host.pl
zabbix-config:
sed -i \
-e 's:# PidFile=/tmp/zabbix_agent2.pid:PidFile=/run/zabbix/zabbix_agent2.pid:' \
-e 's:# LogFile=/tmp/zabbix_agent2.log:LogFile=/var/log/zabbix/zabbix_agent2.log:' \
$(CHROOT)/etc/zabbix/zabbix_agent2.conf
sed -i \
-e 's:LogFile=/tmp/zabbix_proxy.log:LogFile=/var/log/zabbix/zabbix_proxy.log:' \
-e 's:# PidFile=/tmp/zabbix_proxy.pid:PidFile=/run/zabbix/zabbix_proxy.pid:' \
$(CHROOT)/etc/zabbix/zabbix_proxy.conf
sed -i \
-e 's:LogFile=/tmp/zabbix_server.log:LogFile=/var/log/zabbix/zabbix_server.log:' \
-e 's:# PidFile=/tmp/zabbix_server.pid:PidFile=/run/zabbix/zabbix_server.pid:' \
-e 's:# StartPollers=5:StartPollers=15:' \
-e 's:# StartIPMIPollers=0:StartIPMIPollers=5:' \
-e 's:# StartPollersUnreachable=1:StartPollersUnreachable=15:' \
-e 's:# StartPingers=1:StartPingers=25:' \
-e 's:# StartDiscoverers=1:StartDiscoverers=5:' \
-e 's:# JavaGateway=:JavaGateway=127.0.0.1:' \
-e 's:# VMwareCacheSize=8M:VMwareCacheSize=16M:' \
-e 's:# VMwareTimeout=10:VMwareTimeout=30:' \
-e 's:# SNMPTrapperFile=/tmp/zabbix_traps.tmp:SNMPTrapperFile=/var/log/snmptt/snmptt.log:' \
-e 's:# CacheSize=8M:CacheSize=32M:' \
-e 's:# HistoryIndexCacheSize=4M:HistoryIndexCacheSize=8M:' \
-e 's:Timeout=4:Timeout=10:' \
-e 's:^# AlertScriptsPath=.*:AlertScriptsPath=/var/lib/zabbix/alertscripts:' \
-e 's:^# ExternalScripts=.*:ExternalScripts=/var/lib/zabbix/externalscripts:' \
-e 's:# ProxyConfigFrequency=3600:ProxyConfigFrequency=360:' \
-e 's:# ProxyDataFrequency=1:ProxyDataFrequency=60:' \
$(CHROOT)/etc/zabbix/zabbix_server.conf
fping-perm:
chmod u=rwsx,g=rx,o=rx $(CHROOT)/usr/sbin/fping
chmod u=rwsx,g=rx,o=rx $(CHROOT)/usr/sbin/fping6
snmp-conf:
cp -f snmp/snmpd.conf $(CHROOT)/etc/snmp/snmpd.conf
cp -f snmp/snmptrapd.conf $(CHROOT)/etc/snmp/snmptrapd.conf
cp -f snmp/snmptt.conf $(CHROOT)/etc/snmp/snmptt.conf
sed -i \
-e 's:^mode = .*:mode = standalone:' \
-e 's:^net_snmp_perl_enable = .*:net_snmp_perl_enable = 1:' \
-e 's:^translate_log_trap_oid = .*:translate_log_trap_oid = 2:' \
-e 's:^translate_integers = .*:translate_integers = 0:' \
-e 's:^#mibs_environment = .*:mibs_environment = ALL:' \
-e 's.^#date_time_format =.date_time_format = %H:%M:%S %Y/%m/%d.' \
-e 's:^daemon_uid = .*:daemon_uid = zabbix:' \
-e 's:^log_system_enable = .*:log_system_enable = 1:' \
-e 's:^unknown_trap_log_enable = .*:unknown_trap_log_enable = 1:' \
-e 's:^syslog_level = .*:syslog_level = err:' \
-e 's:^syslog_system_level = .*:syslog_system_level = err:' \
$(CHROOT)/etc/snmp/snmptt.ini
mkdir -p $(CHROOT)/var/log/snmptt
chmod 0775 $(CHROOT)/var/log/snmptt
RUN chown zabbix:zabbix /var/log/snmptt
preinstall:
postinstall: systemd-units $(02firstboot) $(cert-renew.sh) $(CHROOT)/var/lib/mysql apache-php zabbix-services zabbix-webapp $(zabbix-userparameter) zabbix-syslog zabbix-config fping-perm snmp-conf

221
appliance/02firstboot.start Executable file
View File

@ -0,0 +1,221 @@
#!/bin/bash
# variables
LABEL="DATA"
DATABASE_PASS=$(head -c 300 /dev/urandom | tr -cd 'a-zA-Z0-9' | head -c 16)
TLD="example.com"
HOST="zabbix"
ORGNAME="Zabbix example"
# start
set -e
[ -e /01firstboot ] && exit 0
[ -e /02firstboot ] || exit 0
# Select type
if [ -f "/$LABEL/etc/zabbix/zabbix_server.conf" ]; then
zabbixtype="server"
elif [ -f "/$LABEL/etc/zabbix/zabbix_proxy.conf" ]; then
zabbixtype="proxy"
else
echo
echo "Should the new appliance be configured as a server or a proxy?"
while read -n1 -r -p "choose [s]erver|[p]roxy: "; do
case $REPLY in
s|S) zabbixtype="server"
break
;;
p|P) zabbixtype="proxy"
break
;;
*) echo " (Invalid option, choose again...)"
;;
esac
done
echo
fi
# Zabbix configuration
if [ "$zabbixtype" == "server" ]; then
if [ ! -L /etc/zabbix/zabbix_server.conf ]; then
if [ ! -f "/$LABEL/etc/zabbix/zabbix_server.conf" ]; then
echo 'Create Zabbix Server config...'
mkdir -p /$LABEL/etc/zabbix
cp /etc/zabbix/zabbix_server.conf /$LABEL/etc/zabbix/zabbix_server.conf
mv /etc/zabbix/zabbix_server.conf /$LABEL/etc/zabbix/zabbix_server.conf.orig
chown -R zabbix:zabbix /$LABEL/etc/zabbix
ln -s /$LABEL/etc/zabbix/zabbix_server.conf /etc/zabbix/zabbix_server.conf
else
echo 'Linking Zabbix Server config...'
cp /$LABEL/etc/zabbix/zabbix_server.conf /$LABEL/etc/zabbix/zabbix_server.conf.alt
rm -f /$LABEL/etc/zabbix/zabbix_server.conf.orig
mv /etc/zabbix/zabbix_server.conf /$LABEL/etc/zabbix/zabbix_server.conf.orig
chown -R zabbix:zabbix /$LABEL/etc/zabbix
ln -s /$LABEL/etc/zabbix/zabbix_server.conf /etc/zabbix/zabbix_server.conf
fi
fi
else
if [ ! -L /etc/zabbix/zabbix_proxy.conf ]; then
if [ ! -f "/$LABEL/etc/zabbix/zabbix_proxy.conf" ]; then
echo 'Create Zabbix Proxy config...'
mkdir -p /$LABEL/etc/zabbix
chown zabbix:zabbix /$LABEL/etc/zabbix
cp /etc/zabbix/zabbix_proxy.conf /$LABEL/etc/zabbix/zabbix_proxy.conf
mv /etc/zabbix/zabbix_proxy.conf /$LABEL/etc/zabbix/zabbix_proxy.conf.orig
sed -i "s:^DBName=.*:DBName=zabbix:" /$LABEL/etc/zabbix/zabbix_proxy.conf
chown -R zabbix:zabbix /$LABEL/etc/zabbix
ln -s /$LABEL/etc/zabbix/zabbix_proxy.conf /etc/zabbix/zabbix_proxy.conf
else
echo 'Linking Zabbix Proxy config...'
cp /$LABEL/etc/zabbix/zabbix_proxy.conf /$LABEL/etc/zabbix/zabbix_proxy.conf.alt
rm -f /$LABEL/etc/zabbix/zabbix_proxy.conf.orig
mv /etc/zabbix/zabbix_proxy.conf /$LABEL/etc/zabbix/zabbix_proxy.conf.orig
chown -R zabbix:zabbix /$LABEL/etc/zabbix
ln -s /$LABEL/etc/zabbix/zabbix_proxy.conf /etc/zabbix/zabbix_proxy.conf
fi
fi
fi
if [ "$zabbixtype" == "server" ]; then
if [ ! -L /var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php ]; then
if [ ! -f "/$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php" ]; then
echo 'Create Zabbix Frontend config...'
mkdir -p /$LABEL/var/www/localhost/htdocs/zabbix/conf
cp /var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php
mv /var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php.orig
ln -s /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php /var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php
else
echo 'Linking Zabbix Frontend config...'
cp /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php.alt
rm -f /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php.orig
mv /var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php.orig
ln -s /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php /var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php
fi
fi
if [ ! -L /var/lib/net-snmp ]; then
echo 'Linking SNMP data directory...'
if [ ! -d "/$LABEL/var/lib/net-snmp" ]; then
mkdir -p /$LABEL/var/lib/net-snmp
cp -a /var/lib/net-snmp/. /$LABEL/var/lib/net-snmp
fi
rm -rf /var/lib/net-snmp.orig
mv /var/lib/net-snmp /var/lib/net-snmp.orig
ln -s /$LABEL/var/lib/net-snmp /var/lib/net-snmp
fi
fi
# Zabbix home directory
if [ ! -L /var/lib/zabbix ]; then
echo 'Linking Zabbix home directory...'
if [ ! -d "/$LABEL/var/lib/zabbix" ]; then
mkdir -p /$LABEL/var/lib/zabbix
chown zabbix:zabbix /$LABEL/var/lib/zabbix
cp -a /var/lib/zabbix/. /$LABEL/var/lib/zabbix
fi
rm -rf /var/lib/zabbix.orig
mv /var/lib/zabbix /var/lib/zabbix.orig
ln -s /$LABEL/var/lib/zabbix /var/lib/zabbix
fi
# Database
if [ ! -L /var/lib/mysql ]; then
systemctl stop mariadb
if [ ! -d "/$LABEL/var/lib/mysql/zabbix" ]; then
echo 'Initialize MariaDB...'
mkdir -p "/$LABEL/var/lib"
rm -rf "/$LABEL/var/lib/mysql"
rm -rf "/$LABEL/var/lib/mysql.orig"
cp -a "/var/lib/mysql" "/$LABEL/var/lib/mysql"
mv "/var/lib/mysql" "/$LABEL/var/lib/mysql.orig"
ln -s "/$LABEL/var/lib/mysql" "/var/lib/mysql"
systemctl start mariadb
sleep 5
echo 'Create Zabbix database...'
mysql -u root -e "CREATE USER 'zabbix'@'localhost' IDENTIFIED BY '$DATABASE_PASS'"
mysql -u root -e "CREATE DATABASE zabbix DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;"
mysql -u root -e "GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost' IDENTIFIED by '$DATABASE_PASS';"
mysql -u root -e "FLUSH PRIVILEGES;"
echo 'Import Zabbix MySQL data'
mysql -u root zabbix < /usr/share/zabbix/database/mysql/schema.sql
if [ "$zabbixtype" == "server" ]; then
mysql -u root zabbix < /usr/share/zabbix/database/mysql/images.sql
mysql -u root zabbix < /usr/share/zabbix/database/mysql/data.sql
fi
else
echo 'Start MariaDB...'
rm -rf "/$LABEL/var/lib/mysql.orig"
mv "/var/lib/mysql" "/$LABEL/var/lib/mysql.orig"
ln -s "/$LABEL/var/lib/mysql" "/var/lib/mysql"
systemctl start mariadb
sleep 5
mysql -u root -e "GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost' IDENTIFIED by '$DATABASE_PASS';"
fi
else
echo 'Set new database password...'
systemctl restart mariadb
sleep 5
mysql -u root -e "GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost' IDENTIFIED by '$DATABASE_PASS';"
fi
# update config with new database password
if [ "$zabbixtype" == "server" ]; then
sed -i "s:.*DBPassword=.*:DBPassword=${DATABASE_PASS}:" /$LABEL/etc/zabbix/zabbix_server.conf
sed -i "s:\$DB\['PASSWORD'\].*:\$DB\['PASSWORD'\] = '${DATABASE_PASS}';:" /$LABEL/var/www/localhost/htdocs/zabbix/conf/zabbix.conf.php
else
sed -i "s:.*DBPassword=.*:DBPassword=${DATABASE_PASS}:" /$LABEL/etc/zabbix/zabbix_proxy.conf
fi
# Certificate
if [ "$zabbixtype" == "server" ]; then
if [ -x "/$LABEL/etc/ssl/cert-renew.sh" ]; then
# angepaßtes Zertifikat vorhanden (kein example)
if [ ! -L /etc/ssl/cert-renew.sh ]; then
rm -f "/$LABEL/etc/ssl/cert-renew.sh.orig"
mv "/etc/ssl/cert-renew.sh" "/$LABEL/etc/ssl/cert-renew.sh.orig"
else
rm -f "/etc/ssl/cert-renew.sh"
fi
ln -s "/$LABEL/etc/ssl/cert-renew.sh" "/etc/ssl/cert-renew.sh"
else
echo 'Create example certificate...'
mkdir -p "/$LABEL/CERTS/KEYS/"
mkdir -p "/$LABEL/CERTS/$HOST.$TLD"
echo "FQDN = $HOST.$TLD" > "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf"
echo "ORGNAME = $ORGNAME" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf"
echo "ALTNAMES = DNS:$HOST.$TLD , DNS:$TLD" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf"
echo -e "\n[ req ]\ndefault_bits = 4096\ndefault_md = sha256\nprompt = no\nencrypt_key = no\ndistinguished_name = dn\nreq_extensions = req_ext\ndefault_keyfile = ../KEYS/\$FQDN-key.pem\n" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf"
echo -e "\n[ dn ]\nC = DE\nO = \$ORGNAME\nCN = \$FQDN\n" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf"
echo -e "\n[ req_ext ]\nsubjectAltName = \$ALTNAMES" >> "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf"
openssl req -x509 -new -config "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD.cnf" -out "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-cert.pem" -keyout "/$LABEL/CERTS/KEYS/$HOST.$TLD-key.pem"
cp "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-cert.pem" "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-fullchain.pem"
touch "/$LABEL/CERTS/$HOST.$TLD/$HOST.$TLD-chain.pem"
fi
rm -rf /etc/ssl/apache2
mkdir -p /etc/ssl
ln -sf "/$LABEL/etc/ssl/apache2" "/etc/ssl/apache2"
/etc/ssl/cert-renew.sh
fi
systemctl enable mariadb
systemctl enable zabbix-agent2
if [ "$zabbixtype" == "server" ]; then
systemctl enable zabbix-server
systemctl enable apache2
else
systemctl enable zabbix-proxy
fi
systemctl restart zabbix-agent2
if [ "$zabbixtype" == "server" ]; then
systemctl restart zabbix-server
systemctl restart apache2
else
systemctl restart zabbix-proxy
fi
rm /02firstboot

32
appliance/MySQL-Backup.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
DIR="/DATA/Backup/MySQL"
if [ -z $1 ]; then
echo "database name missing! use --all for all db's"
exit 1;
elif [ $1 = '--all' ]; then
echo "full backup"
for i in `mysqlshow --defaults-file=/root/.my.cnf | awk '{print $2}' | grep -v Databases`; do
if [ "$i" != "information_schema" ] && [ "$i" != "performance_schema" ]; then
if test -f ${DIR}/${i}.sql; then
echo "Move ${DIR}/${i}.sql to ${DIR}/${i}.sql.1"
mv ${DIR}/${i}.sql ${DIR}/${i}.sql.1
fi
echo "dump ${i} to ${DIR}/${i}.sgl"
mysqldump --defaults-file=/root/.my.cnf --single-transaction --events --opt -QF -r${DIR}/${i}.sql $i
chmod 600 ${DIR}/${i}.sql
fi
done;
elif [ -n $1 ]; then
echo "Starting backup of $1"
if test -f $DIR/$1.sql; then
echo "Move $DIR/$1.sql to $DIR/$1.sql.1"
mv ${DIR}/${1}.sql ${DIR}/${1}.sql.1
fi
mysqldump --defaults-file=/root/.my.cnf --single-transaction --opt -QF -r${DIR}/${1}.sql $1
chmod 600 ${DIR}/${1}.sql
fi
echo "Done"
exit 0;

8
appliance/backup.service Normal file
View File

@ -0,0 +1,8 @@
[Unit]
Description=execute backup tasks
RefuseManualStart=no
RefuseManualStop=yes
[Service]
Type=oneshot
ExecStart=/usr/local/bin/MySQL-Backup.sh --all

12
appliance/backup.timer Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=execute backup tasks
RefuseManualStart=no
RefuseManualStop=no
[Timer]
Persistent=false
OnCalendar=Sun *-*-* 02:19:00
Unit=backup.service
[Install]
WantedBy=default.target

View File

@ -0,0 +1,8 @@
[Unit]
Description=renew certificates from git store
RefuseManualStart=no
RefuseManualStop=yes
[Service]
Type=oneshot
ExecStart=/etc/ssl/cert-renew.sh

52
appliance/cert-renew.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/bash
HOST="zabbix"
TLD="example.com"
FQDN="$HOST.$TLD"
LABEL="DATA"
CERT_DIR=/$LABEL/CERTS
CERT_APACHE=/$LABEL/etc/ssl/apache2
GETREPO=""
GETUSER=""
GETPASS=""
function getCurrentVersion() {
# Get hash from latest revision
git log --format=format:%H -1
}
cd $CERT_DIR
if [ -z "$GETREPO" ]; then
GIT_REVISION=0
GIT_NEW_REVISION=1
cd $FQDN
elif [ ! -d "$FQDN" ]; then
GIT_REVISION=0
git clone "https://$GETUSER:$GETPASS@$GETREPO"
cd $FQDN
GIT_NEW_REVISION=$(getCurrentVersion)
else
cd $FQDN
GIT_REVISION=$(getCurrentVersion)
git commit -m "CRON: auto commit"
git fetch
git merge origin/master -m "Auto Merge"
GIT_NEW_REVISION=$(getCurrentVersion)
fi
echo "old: $GIT_REVISION"
echo "new: $GIT_NEW_REVISION"
if [ $GIT_REVISION != $GIT_NEW_REVISION ]
then
echo "Update Apache certificate..."
mkdir -p $CERT_APACHE
cp $CERT_DIR/$FQDN/$FQDN-fullchain.pem $CERT_APACHE/server.crt
cp $CERT_DIR/KEYS/$FQDN-key.pem $CERT_APACHE/server.key
echo "Restarting Apache..."
systemctl is-active --quiet apache2 && systemctl restart apache2
fi
exit 0

View File

@ -0,0 +1,12 @@
[Unit]
Description=renew certificates from git store
RefuseManualStart=no
RefuseManualStop=no
[Timer]
Persistent=false
OnCalendar=Sun *-*-* 04:03:00
Unit=cert-renew.service
[Install]
WantedBy=default.target

11
mariadb/my.cnf.root Normal file
View File

@ -0,0 +1,11 @@
[mysqladmin]
user = root
password = gentoo
[mysql]
user = root
password = gentoo
[client]
user = root
password = gentoo

2
package.accept_keywords Normal file
View File

@ -0,0 +1,2 @@
# Zabbix
net-analyzer/snmptt

2
package.mask Normal file
View File

@ -0,0 +1,2 @@
# nur LTS-Versionen 6.0.x bauen
>=net-analyzer/zabbix-6.1

12
package.use Normal file
View File

@ -0,0 +1,12 @@
# Zabbix
app-admin/rsyslog dbi mysql openssl snmp systemd
app-eselect/eselect-php apache2
app-text/poppler -introspection -jpeg -jpeg2k
dev-java/openjdk-bin headless-awt
dev-lang/php apache2 bcmath curl gd ldap mysql mysqli odbc sockets sysvipc truetype xmlreader xmlwriter
media-libs/gd jpeg png
net-analyzer/zabbix -agent agent2 curl frontend java ldap libxml2 mysql odbc openipmi -postgres proxy server snmp ssh xmpp
net-analyzer/zabbix-headers -agent agent2 curl frontend java ldap libxml2 mysql odbc openipmi -postgres proxy server snmp ssh xmpp
net-analyzer/net-snmp perl
net-analyzer/fping suid
net-print/cups-filters -foomatic -postscript

2
snmp/snmpd.conf Normal file
View File

@ -0,0 +1,2 @@
#mibs +SOME-OTHER-SPIFFY-MIB
mibs +ALL

2
snmp/snmptrapd.conf Normal file
View File

@ -0,0 +1,2 @@
traphandle default /usr/sbin/snmptt
disableAuthorization yes

2
snmp/snmptt.conf Normal file
View File

@ -0,0 +1,2 @@
EVENT general .* "General event" Normal
FORMAT ZBXTRAP $aA $ar severity:$s $Fn$+*

2
va-zabbix.cfg Normal file
View File

@ -0,0 +1,2 @@
REPO_NAMES += unitas-zabbix
REPO_URI_unitas-zabbix = https://git.unitas-network.de/Gentoo/unitas-zabbix.git

20
world Normal file
View File

@ -0,0 +1,20 @@
app-admin/rsyslog
dev-db/mariadb
dev-db/phpmyadmin
dev-java/openjdk-bin:11
dev-perl/Config-General
dev-perl/JSON-RPC
dev-perl/JSON-XS
dev-perl/libwww-perl
dev-tcltk/expect
net-analyzer/snmp-lldp
net-analyzer/net-snmp
net-analyzer/nmap
net-analyzer/snmptt
net-analyzer/traceroute
net-dns/bind-tools
net-im/sendxmpp
net-misc/netkit-telnetd
sys-apps/ipmitool
sys-libs/openipmi
sys-process/lsof

View File

@ -0,0 +1 @@
UserParameter=mysql.status[*],echo "show global status where Variable_name='$1';" | HOME=/etc/ mysql -N | awk '{print $$2}'

View File

@ -0,0 +1,19 @@
# provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
#enables omrpog module
$ModLoad omprog
$template RFC3164fmt,"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%"
$template network-fmt,"%TIMESTAMP:::date-rfc3339% [%fromhost-ip%] %pri-text% %syslogtag%%msg%\n"
#exclude unwanted messages(examples):
:msg, contains, "Child connection from" stop
:msg, contains, "exit after auth (ubnt): Disconnect received" stop
:msg, contains, "password auth succeeded for 'ubnt' from" stop
:msg, contains, "exit before auth: Exited normally" stop
if $fromhost-ip != '127.0.0.1' then {
action(type="omprog" binary="/etc/zabbix/scripts/zabbix_syslog_lkp_host.pl" template="network-fmt")
stop
}

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
<version>2.0</version>
<date>2015-03-13T14:27:56Z</date>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<templates>
<template>
<template>Template_Syslog</template>
<name>Template_Syslog</name>
<description/>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<applications>
<application>
<name>Log</name>
</application>
</applications>
<items>
<item>
<name>Syslog</name>
<type>2</type>
<snmp_community/>
<multiplier>0</multiplier>
<snmp_oid/>
<key>syslog</key>
<delay>0</delay>
<history>3</history>
<trends>365</trends>
<status>0</status>
<value_type>2</value_type>
<allowed_hosts/>
<units/>
<delta>0</delta>
<snmpv3_contextname/>
<snmpv3_securityname/>
<snmpv3_securitylevel>0</snmpv3_securitylevel>
<snmpv3_authprotocol>0</snmpv3_authprotocol>
<snmpv3_authpassphrase/>
<snmpv3_privprotocol>0</snmpv3_privprotocol>
<snmpv3_privpassphrase/>
<formula>1</formula>
<delay_flex/>
<params/>
<ipmi_sensor/>
<data_type>0</data_type>
<authtype>0</authtype>
<username/>
<password/>
<publickey/>
<privatekey/>
<port/>
<description/>
<inventory_link>0</inventory_link>
<applications>
<application>
<name>Log</name>
</application>
</applications>
<valuemap/>
<logtimefmt>yyyyxMMxddxhhxmmxssxxxxxx</logtimefmt>
</item>
</items>
<discovery_rules/>
<macros/>
<templates/>
<screens/>
</template>
</templates>
<triggers>
<trigger>
<expression>({Template_Syslog:syslog.str(.alert)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
<name>[SYSLOG] Alert message received</name>
<url/>
<status>0</status>
<priority>4</priority>
<description/>
<type>0</type>
<dependencies/>
</trigger>
<trigger>
<expression>({Template_Syslog:syslog.str(.crit)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
<name>[SYSLOG] Critical message received</name>
<url/>
<status>0</status>
<priority>3</priority>
<description/>
<type>0</type>
<dependencies/>
</trigger>
<trigger>
<expression>({Template_Syslog:syslog.str(.emerg)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
<name>[SYSLOG] Emergency message received</name>
<url/>
<status>0</status>
<priority>5</priority>
<description/>
<type>0</type>
<dependencies/>
</trigger>
<trigger>
<expression>({Template_Syslog:syslog.str(.err)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
<name>[SYSLOG] Error received</name>
<url/>
<status>0</status>
<priority>2</priority>
<description/>
<type>0</type>
<dependencies/>
</trigger>
<trigger>
<expression>({Template_Syslog:syslog.str(.warning)}=1)and({Template_Syslog:syslog.nodata(900)}=0)</expression>
<name>[SYSLOG] Warning received</name>
<url/>
<status>0</status>
<priority>1</priority>
<description/>
<type>0</type>
<dependencies/>
</trigger>
</triggers>
</zabbix_export>

View File

@ -0,0 +1,587 @@
package ZabbixAPI;
use Data::Dumper;
use LWP;
use JSON::XS;
use MIME::Base64 qw(encode_base64);
my @no_auth_methods = ('user.login','apiinfo.version');
sub new {
my $class = shift;
my $args = shift;
my $api_url = $args->{api_url}
|| 'http://localhost/zabbix/api_jsonrpc.php';
my $username = $args->{username} || 'Admin';
my $password = $args->{password} || 'zabbix';
my $self = bless {
api_url => $api_url,
username => $username,
password => $password,
ua => LWP::UserAgent->new(),
auth => undef,
id => 1,
}, $class;
$self->{req} = HTTP::Request->new( POST => $self->{api_url} );
$self->{req}->content_type('application/json-rpc');
return $self;
}
sub id {
my $self = shift;
return $self->{id}++;
}
sub prepare_auth {
my $self = shift;
my $method = shift;
if (grep /$method/,@no_auth_methods) {
return undef;
}
else
{
return $self->{auth};
}
};
sub do {
my $self = shift;
my $method = shift;
my $params = shift;
my $json = JSON::XS->new->utf8->encode(
{
jsonrpc => '2.0',
method => $method,
params => $params,
id => $self->id,
auth => $self->prepare_auth($method)
}
);
$self->{req}->content($json);
# Pass request to the user agent and get a response back
my $res = $self->{ua}->request( $self->{req} );
# Check the outcome of the response
if ( $res->is_success ) {
my $return = JSON::XS->new->utf8->decode( $res->content );
die $return->{error}->{data}."\n" if $return->{error};
return $return->{result};
}
else {
die $res->status_line, "\n";
}
}
sub do_raw {
my $self = shift;
my $method = shift;
my $params = shift;
my $json = JSON::XS->new->utf8->encode(
{
jsonrpc => '2.0',
method => $method,
params => JSON::XS->new->utf8->decode($params),
id => $self->id,
auth => $self->prepare_auth($method)
}
);
$self->{req}->content($json);
# Pass request to the user agent and get a response back
my $res = $self->{ua}->request( $self->{req} );
# Check the outcome of the response
if ( $res->is_success ) {
my $return = JSON::XS->new->utf8->decode( $res->content );
die $return->{error}->{data}."\n" if $return->{error};
return $return->{result};
}
else {
die $res->status_line, "\n";
}
}
sub import_configuration_from_file {
my $self = shift;
my $file = shift;
my $configuration;
{
local $/ = undef;
open(my $fh,'<:encoding(UTF-8)', $file) or die "Error opening $file: $!";
$configuration = <$fh>;
close $fh;
}
my $json = <<'END_PARAMS';
{
"format": "xml",
"rules": {
"groups": {
"createMissing": true
},
"hosts": {
"createMissing": true,
"updateExisting": true
},
"templates": {
"createMissing": true,
"updateExisting": true
},
"templateLinkage": {
"createMissing": true
},
"templateScreens": {
"createMissing": true,
"updateExisting": true,
"deleteMissing": true
},
"applications": {
"createMissing": true,
"deleteMissing": true
},
"discoveryRules": {
"createMissing": true,
"updateExisting": true,
"deleteMissing": true
},
"items": {
"createMissing": true,
"updateExisting": true,
"deleteMissing": true
},
"triggers": {
"createMissing": true,
"updateExisting": true,
"deleteMissing": true
},
"graphs": {
"createMissing": true,
"updateExisting": true,
"deleteMissing": true
},
"screens": {
"createMissing": true,
"updateExisting": true
},
"maps": {
"createMissing": true,
"updateExisting": true
},
"images": {
"createMissing": true,
"updateExisting": true
},
"valueMaps": {
"createMissing": true,
"updateExisting": true
}
},
"source": ""
}
END_PARAMS
my $params = JSON::XS->new->utf8->decode($json);
$params->{source}=$configuration;
$self->do('configuration.import', $params);
}
sub login {
my $self = shift;
my $params = {
user => $self->{username},
password => $self->{password}
};
my $content = $self->do("user.login",$params);
$self->{auth}=$content;
}
sub logout {
my $self = shift;
$self->do( 'user.logout', {} );
}
sub create_or_update_mediatype {
my $self = shift;
my $params = shift;
my $result;
eval { #try to create JSON
$result = $self->do('mediatype.create', $params);
};
if ($@) {
if($@ =~ /already exists/) {
warn "WARN: $params->{description} already exists. Updating instead..."."\n";
#get mediatypeid
$json = { output => ['mediatypeid'], filter =>{description=>[$params->{description}]}};
my $id = $self->do('mediatype.get',$json);
$params->{mediatypeid}= $id->[0]->{mediatypeid};
#update instead of creating....
$result = $self->do('mediatype.update', $params);
return $result;
}
else {
die $@;
}
}
else {
return $result;
}
}
sub create_or_update_user {
my $self = shift;
my $params = shift;
my $result;
eval { #try to create JSON
$result = $self->do('user.create', $params);
};
if ($@) {
if($@ =~ /already exists/) {
warn "WARN: $params->{alias} already exists. Updating instead..."."\n";
#get mediatypeid
$json = { output => ['userid'], filter =>{alias=>[$params->{alias}]}};
my $id = $self->do('user.get',$json);
$params->{userid}= $id->[0]->{userid};
#update instead of creating....
my $medias = $params->{user_medias}->[0];
delete $params->{user_medias}; # remove user_medias, not possible in 'user.update' call
$result = $self->do('user.update', $params);
my $result_media = $self->do('user.updatemedia',{users => [ {userid=>$params->{userid}} ],
medias => $medias
});
return $result;
}
else {
die $@;
}
}
else {
return $result;
}
}
sub create_or_update_action {
my $self = shift;
my $params = shift;
my $result;
eval { #try to create JSON
$result = $self->do('action.create', $params);
};
if ($@) {
if($@ =~ /already exists/) {
warn "WARN: $params->{name} already exists. Updating instead..."."\n";
#get mediatypeid
$json = { output => ['actionid'], filter =>{name=>[$params->{name}]}};
my $id = $self->do('action.get',$json);
$params->{actionid}= $id->[0]->{actionid};
#update instead of creating....
delete $params->{eventsource}; #cannot be update, must be removed
$result = $self->do('action.update', $params);
return $result;
}
else {
die $@;
}
}
else {
return $result;
}
}
sub create_or_update_drule {
my $self = shift;
my $params = shift;
my $result;
eval { #try to create JSON
$result = $self->do('drule.create', $params);
};
if ($@) {
if($@ =~ /already exists/) {
warn "WARN: $params->{name} already exists. Updating instead..."."\n";
$json = { output => ['druleid'], filter =>{name=>[$params->{name}]}};
my $id = $self->do('drule.get',$json);
$params->{druleid}= $id->[0]->{druleid};
#update instead of creating....
$result = $self->do('drule.update', $params);
return $result;
}
else {
die $@;
}
}
else {
return $result;
}
}
sub get_template_id {
my $self = shift;
my $template_name = shift;
my $json = { output => ['host','templateid'], filter =>{host=>[$template_name]}};
my $result = $self->do('template.get',$json);
return $result->[0]->{templateid};
}
sub get_hostgroup_id {
my $self = shift;
my $hgroup_name = shift;
my $json = { output => ['groupid'], filter =>{name=>[$hgroup_name]}};
my $result = $self->do('hostgroup.get',$json);
return $result->[0]->{groupid};
}
sub get_host_id {
my $self = shift;
my $host_name = shift;
my $json = { output => ['hostid'], filter =>{host=>[$host_name]}};
my $result = $self->do('host.get',$json);
return $result->[0]->{hostid};
}
sub get_host_by_name {
my $self = shift;
my $host_name = shift;
my $json = {
output => ['hostid'],
filter =>{host=>[$host_name]},
selectGroups => ['groupid','name'],
selectParentTemplates => ['templateid','name'],
selectMacros => ['macro','value']
};
my $result = $self->do('host.get',$json);
return $result->[0];
}
sub create_or_merge_host {
my $self = shift;
my $host_name = shift;
my $params = shift;
my $result;
my $hostid = $self->get_host_id($host_name);
if ($hostid) {
print "WARN: Cannot create host $host_name ... going to merge instead\n";
#print $hostid."\n";
#update (merge mode currently)
$params->{hostid}=$hostid;
my $host = $self->get_host_by_name($host_name);
if ($params->{templates}) {
#merge with already existed
my @templates;
foreach my $template (@{$params->{templates}}){
push @templates,$template->{templateid};
}
foreach my $template (@{$host->{parentTemplates}}){
push @templates,$template->{templateid};
}
my %seen = (); # see http://perldoc.perl.org/perlfaq4.html#How-can-I-remove-duplicate-elements-from-a-list-or-array%3f
@templates = grep { ! $seen{ $_ }++ } @templates;
my $i=0;
delete $params->{templates};
foreach my $templateid (@templates) {
$params->{templates}->[$i]->{templateid} = $templateid;
$i++;
}
}
if ($params->{groups}) {
#merge with already existed
my @groups;
foreach my $group (@{$params->{groups}}){
push @groups,$group->{groupid};
}
foreach my $group (@{$host->{groups}}){
push @groups,$group->{groupid};
}
my %seen = (); # see http://perldoc.perl.org/perlfaq4.html#How-can-I-remove-duplicate-elements-from-a-list-or-array%3f
@groups = grep { ! $seen{ $_ }++ } @groups;
my $i=0;
delete $params->{groups};
foreach my $groupid (@groups) {
$params->{groups}->[$i]->{groupid} = $groupid;
$i++;
}
}
if ($params->{macros}) {
#merge with already existed
my @macros;
foreach my $macro (@{$params->{macros}}){
push @macros,
{
macro => $macro->{macro},
value => $macro->{value}
};
}
foreach my $macro (@{$host->{macros}}){
push @macros,
{
macro => $macro->{macro},
value => $macro->{value}
};
}
my %seen = (); # see http://perldoc.perl.org/perlfaq4.html#How-can-I-remove-duplicate-elements-from-a-list-or-array%3f
@macros = grep { ! $seen{ $_->{macro} }++ } @macros;
my $i=0;
delete $params->{macros};
foreach my $macro (@macros) {
$params->{macros}->[$i] = $macro;
$i++;
}
}
if ($params->{interfaces}) {
#merge with already existed
#warn "WARN: host interfaces merge is not supported yet... skipping interfaces part\n";
delete $params->{interfaces};
}
#print Dumper $params;
$result = $self->do('host.update', $params);
}
else {
#create
$params->{host}=$host_name;
#print Dumper $params;
$result = $self->do('host.create', $params);
}
return $result;
}
sub import_image_from_file {
my $self = shift;
my $file = shift;
my $imagename = shift || $file;
my $imagetype = shift || 1; # 1 - icon , 2 - background
my $image;
my $result;
my $json;
{
local $/ = undef;
open(my $fh,, $file) or die "Error opening $file: $!";
$image = <$fh>;
close $fh;
}
my $params = {name => $imagename, imagetype => 1, image => encode_base64($image)};
eval {#try to import image
$result = $self->do('image.create', $params);
};
if ($@) {
if($@ =~ /already exists/) {
warn "WARN: $params->{name} already exists. Updating instead..."."\n";
#get imageid and update instead
$json = { output => ['imageid'], filter =>{name=>[$params->{name}]}};
my $id = $self->do('image.get',$json);
$params->{imageid}= $id->[0]->{imageid};
delete($params->{imagetype});
#update instead of creating....
$result = $self->do('image.update', $params);
return $result;
}
else {
die $@;
}
}
else {
return $result;
}
}
1;

View File

@ -0,0 +1,5 @@
url = http://localhost/zabbix/api_jsonrpc.php
user = Admin
password = zabbix
server = localhost
debug = 0

View File

@ -0,0 +1,207 @@
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use FindBin qw($Bin);
use lib "$Bin/lib";
use Data::Dumper;
use Config::General;
use ZabbixAPI;
our $VERSION = 4.0;
my $conf;
$conf = eval {Config::General->new('/usr/local/etc/zabbix_syslog.cfg')};
if ($@) {
eval {$conf = Config::General->new('/etc/zabbix/zabbix_syslog.cfg')};
if ($@) {die "Please check that config file is available as /usr/local/etc/zabbix_syslog.cfg or /etc/zabbix/zabbix_syslog.cfg\n";}
}
my %Config = $conf->getall;
#Authenticate yourself
my $url = $Config{'url'} || die "URL is missing in zabbix_syslog.cfg\n";
my $user = $Config{'user'} || die "API user is missing in zabbix_syslog.cfg\n";
my $password = $Config{'password'} || die "API user password is missing in zabbix_syslog.cfg\n";
my $server = $Config{'server'} || die "server hostname is missing in zabbix_syslog.cfg\n";
my $debug = $Config{'debug'};
my ( $authID, $response, $json );
my $zbx = ZabbixAPI->new( { api_url => $url, username => $user, password => $password } );
$zbx->login();
my $syslog_url_base = 'history.php?action=showvalues';
my @selements;
foreach my $map ( @{ map_get_extended() } ) {
my $mapid=$map->{sysmapid};
#put all map elements into array @selements (so you can update map later!)
@selements = @{ $map->{selements} };
print "INFO: Checking map with mapid $map->{sysmapid}\n";
foreach my $selement (@selements) {
my $syslog_button_exists = 0;
if ( $debug > 0 ) {
print 'Object ID: '
. $selement->{selementid}
. ' Type: '
. $selement->{elementtype}."\n";
}
# elementtype=0 hosts
if ( $selement->{elementtype} == 0 ) {
my $hostid;
#Zabbix API 3.4+
if (exists($selement->{elements}->[0]->{hostid})) {
$hostid = $selement->{elements}->[0]->{hostid};
}
#Zabbix API before 3.4
elsif (exists($selement->{elementid})) {
$hostid = $selement->{elementid};
}
else {
die "Cannot get hostid of selement $selement->{selementid}\n";
}
my $itemid = get_syslogid_by_hostid($hostid);
if ($itemid) {
#and add urls:
my $syslog_exists = 0;
foreach my $syslog_url ( @{ $selement->{urls} } ) {
$syslog_exists = 0;
if ( $syslog_url->{name} =~ 'Syslog' ) {
$syslog_exists = 1;
$syslog_url->{'name'} = 'Syslog';
$syslog_url->{'url'} =
$syslog_url_base
. '&itemids['
. $itemid . ']='
. $itemid;
}
}
if ( $syslog_exists == 0 ) {
#syslog item doesn't exist... add it
push @{ $selement->{urls} },
{
'name' => 'Syslog',
'url' => $syslog_url_base
. '&itemids['
. $itemid . ']='
. $itemid
};
}
}
}
}
map_update($mapid,\@selements);
}
$zbx->logout();
#______SUBS
sub get_syslogid_by_hostid {
my $hostid = shift;
my $params = {
output => ['itemid'],
hostids => $hostid,
filter => {'key_' => 'syslog' },
limit => 1,
};
my $result = $zbx->do('item.get',$params);
# Check if response was successful
if ( !$result ) {
$zbx->logout();
die "item.get failed\n";
}
#return itemid of syslog key (trapper type)
return ${ $result }[0]->{itemid};
}
sub map_get {
#retrieve all maps
my $params = {
output => ['sysmapid']
};
my $result = $zbx->do('map.get',$params);
# Check if response was successful
if ( !$result ) {
$zbx->logout();
die "map.get failed\n";
}
if ( $debug > 1 ) { print Dumper $result; }
return $result;
}
sub map_get_extended {
my $params = {
selectSelements => 'extend',
#sysmapids => $map,
};
my $result = $zbx->do('map.get',$params);
# Check if response was successful
if ( !$result ) {
$zbx->logout();
die "map.get failed\n";
}
if ( $debug > 1 ) {
print Dumper $result;
}
return $result;
}
sub map_update {
my $mapid = shift;
my $selements_ref = shift;
my $params = {
selements => [@{$selements_ref}],
sysmapid => $mapid,
};
my $result;
eval {$result=$zbx->do('map.update',$params);};
if($@){
warn "Failed to update map with mapid $mapid, check for write permissions for this map\n";
}
else {
if ( $debug > 0 ) {
print "About to map.update this\n:";
print Dumper $params;
}
if ( $debug > 0 ) {
print Dumper $result;
}
}
return;
}

View File

@ -0,0 +1,274 @@
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use FindBin qw($Bin);
use lib "$Bin/lib";
use Data::Dumper;
use Config::General;
use ZabbixAPI;
use English '-no_match_vars';
use MIME::Base64 qw(encode_base64);
use IO::Socket::INET;
use Storable qw(lock_store lock_retrieve);
our $VERSION = 4.0;
my $CACHE_TIMEOUT = 600;
my $CACHE_DIR = '/tmp/zabbix_syslog_cache_n';
die "No argumets required anymore since script version 3.0\n" if @ARGV > 0;
my $conf;
$conf = eval {Config::General->new('/usr/local/etc/zabbix_syslog.cfg')};
if ($@) {
eval {$conf = Config::General->new('/etc/zabbix/zabbix_syslog.cfg')};
if ($@) {die "Please check that config file is available as /usr/local/etc/zabbix_syslog.cfg or /etc/zabbix/zabbix_syslog.cfg\n";}
}
my %Config = $conf->getall;
#Authenticate yourself
my $url = $Config{'url'} || die "URL is missing in zabbix_syslog.cfg\n";
my $user = $Config{'user'} || die "API user is missing in zabbix_syslog.cfg\n";
my $password = $Config{'password'} || die "API user password is missing in zabbix_syslog.cfg\n";
my $server = $Config{'server'} || die "server hostname is missing in zabbix_syslog.cfg\n";
my $zbx;
my $debug = $Config{'debug'};
my ( $authID, $response, $json );
#IP regex patter part
my $ipv4_octet = q/(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/;
#rsyslog omprog loop
#http://www.rsyslog.com/doc/master/configuration/modules/omprog.html
while (defined(my $message = <>)) {
chomp($message);
#get ip from message
my $ip;
if ( $message =~ / \[ ((?:$ipv4_octet[.]){3}${ipv4_octet}) \]/msx ) {
$ip = $1;
}
else {
warn "No IP in square brackets found in '$message', cannot continue\n";
next;
}
my $hostname = ${retrieve_from_store($ip)}->{'hostname'};
if ( !defined $hostname ) {
my $result;
$zbx = ZabbixAPI->new( { api_url => $url, username => $user, password => $password } );
$zbx->login();
my @hosts_found;
my $hostid;
my @hostinterfaces;
eval {@hostinterfaces=hostinterface_get($ip)};
if($@){
warn "Failed to retrieve any host interface with IP = $ip. Unable to bind message to item, skipping\n";
next;
}
foreach my $host (@hostinterfaces) {
$hostid = $host->{'hostid'};
if ( grep { /$hostid/msx } @hosts_found ) {
next;
}#check if $hostid already is in array then skip(next)
else { push @hosts_found, $hostid; }
#now get hostname
if ( get_zbx_trapper_syslogid_by_hostid($hostid) ) {
my $result = host_get($hostid);
#return hostname if possible
if ( $result->{'host'} ) {
if ( $result->{'proxy_hostid'} == 0 ) #check if host monitored directly or via proxy
{
#lease $server as is
}
else {
#assume that rsyslogd and zabbix_proxy are on the same server
$server = 'localhost';
}
$hostname = $result->{'host'};
}
last;
}
}
$zbx->logout();
store_message( $ip, $hostname );
}
zabbix_send( $server, $hostname, 'syslog', $message );
}
#______SUBS
sub hostinterface_get {
my $ip = shift;
my $params = {
output => [ 'ip', 'hostid' ],
filter => { ip => $ip, }
};
my $result = $zbx->do('hostinterface.get',$params);
if ( $debug > 0 ) { print Dumper $result; }
# Check if response was successful (not empty array in result)
if ( !@{ $result } ) {
$zbx->logout();
die "hostinterface.get failed\n";
}
return @{ $result };
}
sub get_zbx_trapper_syslogid_by_hostid {
my $hostid = shift;
my $params = {
output => ['itemid'],
hostids => $hostid,
search => {
'key_' => 'syslog',
type => 2, #type => 2 is zabbix_trapper
status => 0,
},
limit => 1,
};
my $result = $zbx->do('item.get',$params);
if ( $debug > 0 ) { print Dumper $result; }
# Check if response was successful
if ( !@{ $result } ) {
warn "item.get failed\n";
}
#return itemid of syslog key (trapper type)
return ${ $result }[0]->{itemid};
}
sub host_get {
my $hostid = shift;
my $params = {
hostids => [$hostid],
output => [ 'host', 'proxy_hostid', 'status' ],
filter => { status => 0, }, # only use hosts enabled
limit => 1,
};
my $result = $zbx->do('host.get',$params);
if ( $debug > 0 ) { print Dumper $result; }
# Check if response was successful
if ( !$result ) {
$zbx->logout();
die "host.get failed\n";
}
return ${ $result }[0]; #return result
}
sub zabbix_send {
my $zabbixserver = shift;
my $hostname = shift;
my $item = shift;
my $data = shift;
my $SOCK_TIMEOUT = 10;
my $SOCK_RECV_LENGTH = 1024;
my $result;
my $request =
sprintf
"<req>\n<host>%s</host>\n<key>%s</key>\n<data>%s</data>\n</req>\n",
encode_base64($hostname), encode_base64($item), encode_base64($data);
my $packet = "ZBXD\1" . pack('V', length($request)) . "\0\0\0\0" . $request;
my $sock = IO::Socket::INET->new(
PeerAddr => $zabbixserver,
PeerPort => '10051',
Proto => 'tcp',
Timeout => $SOCK_TIMEOUT
);
die "Could not create socket: $ERRNO\n" unless $sock;
$sock->send($packet);
my @handles = IO::Select->new($sock)->can_read($SOCK_TIMEOUT);
if ( $debug > 0 ) { print "host - $hostname, item - $item, data - $data\n"; }
if ( scalar(@handles) > 0 ) {
$sock->recv( $result, $SOCK_RECV_LENGTH );
if ( $debug > 0 ) {
print "answer from zabbix server $zabbixserver: $result\n";
}
}
else {
if ( $debug > 0 ) { print "no answer from zabbix server\n"; }
}
$sock->close();
return;
}
#helpers
sub store_message {
my $ip = shift;
my $hostname = shift;
my $storage_file = $CACHE_DIR;
my ( $stored, $to_store );
$to_store->{$ip} = {
hostname => $hostname,
created => time()
};
if ( -f $storage_file ) {
$stored = lock_retrieve $storage_file;
lock_store { %{$stored}, %{$to_store} }, $storage_file;
}
else {
#first time file creation, apply proper file permissions and store only single event
lock_store $to_store, $storage_file;
chmod 0666, $storage_file;
}
}
sub retrieve_from_store {
my $ip = shift;
my $storage_file = $CACHE_DIR;
my $stored;
my $message_to_retrieve;
if ( -f $storage_file ) {
$stored = lock_retrieve $storage_file;
#remove expired from cache
if (defined($stored->{$ip})){
if (time() - $stored->{$ip}->{created} > $CACHE_TIMEOUT){
delete $stored->{$ip};
lock_store $stored, $storage_file;
}
else {
$message_to_retrieve = $stored->{$ip};
}
}
}
return \$message_to_retrieve;
}