Files
shell_sequencer/seqs/snmp.sh

583 lines
16 KiB
Bash
Executable File

#!/bin/bash
seqDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
toolName="snmpd"
toolConfigLoc="/etc/snmp"
toolConfig="${toolConfigLoc}/snmpd.conf"
toolSysUser="Debian-snmp"
step_config() {
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Install packages for $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
if [ $QUIET != 0 ]; then
exe apt-get -qq install $toolName
else
exe apt install $toolName
fi
endReturn -o $? "$toolName installation failed"
}
step_2_info() {
echoinfoArgs "[-s]"
echo "Setup snmp v3 access"
echoinfo " -s : Stop after creating authentication entry"
}
step_2_alias() { ALIAS="v3access"; }
step_2() {
#
## Create authentication entry
exep "cat \"$v3AuthLoc\" | grep -e '^\s*usmUser'"
if [ "$?" == "0" ]; then
echoseq
exe read -p "User entry found. Continue: y/n(default)? " answer
case $answer in
[yY])
echoseq
echoseq "Continuing installation..."
;;
*)
echoseq
echoseq "Installation aborted"
return 1;
;;
esac
fi
read -p "SNMPv3 Username: " v3User
read -p "SNMPv3 Password: " v3Pass
echoseq
read -p "Repeat Password: " v3Pass2
if [ "$v3Pass" != "$v3Pass2" ] ; then
echoerr " [E] Password mismatch"
return 1
fi
echoseq
exe service snmpd stop
# this line will be replaced on start of snmpd with a line starting with:
# usmUser
v3AuthEntry="createUser ${v3User} SHA \"${v3Pass}\" DES"
addConf -a "$v3AuthEntry" "$v3AuthLoc"
shift
if [ ! -z $1 ] && [ "$1" == "-s" ] ; then
echoseq " [I] Stop after creating authentication config"
exe service snmpd start
return 0
fi
#
## Add custom base configuration
addConf -c "" "${toolConfig}"
exe cp "${seqDir}/snmpd.conf" "${toolConfig}"
#
## Add username as rouser
exe sed -i "s/authOnlyUser/${v3User}/" "$toolConfig"
#
## Write syslocation
exe read -p "sysLocation: " v3Location
exe read -p "sysContact (name <webmaster@example.com>): " v3Contact
exe sed -i "s/\(sysLocation\s*\).*/\1${v3Location}/" "$toolConfig"
exe sed -i "s/\(sysContact\s*\).*/\1${v3Contact}/" "$toolConfig"
exe service snmpd start
}
v3AuthLoc="/var/lib/snmp/snmpd.conf"
step_5_info() {
echoinfoArgs "[INTERFACE]"
echo "Add ufw rules for port 161 udp"
echoinfo " [INTERFACE] (default: eth0)"
}
step_5_alias() { ALIAS="ufw"; }
step_5() {
shift
local lInterface="eth0"
[ ! -z "$1" ] && lInterface="$1"
# Check if interface exists
ip -br a | grep -E "^$lInterface" >>/dev/null 2>&1
endReturn -o $? "Interface $lInterface does not exist"
exe ufw allow in on $lInterface to any port 161 proto udp comment "snmp"
}
step_20_info() { echo "Extend $toolName for Raspberry Pi"; }
step_20_alias() { ALIAS="raspberry"; }
step_20() {
checkExtend raspberry
if [ "$?" != "0" ]; then
return 1
fi
exe wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/raspberry.sh -O "${rpiExtendLoc}"
endReturn -o $? "Download failed"
exe chmod +x "$rpiExtendLoc"
addConf -a "extend raspberry /etc/snmp/raspberry.sh" "$toolConfig"
# VCHI initialization failed fix
exe usermod -aG video ${toolSysUser}
addConf -s "$rpiSudoersContent" "$rpiSudoersLoc"
exe service snmpd restart
}
rpiExtendLoc="${toolConfigLoc}/raspberry.sh"
rpiSudoersLoc="/etc/sudoers.d/snmprpi"
rpiSudoersContent="${toolSysUser} ALL=(ALL) NOPASSWD: /etc/snmp/raspberry.sh, /usr/bin/vcgencmd*"
step_22_info() { echo "Extend $toolName with OS update availablity"; }
step_22_alias() { ALIAS="osupdate"; }
step_22() {
checkExtend osupdate
if [ "$?" != "0" ]; then
return 1
fi
exe wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/osupdate -O "${osUpdateExtendLoc}"
endReturn -o $? "Download failed"
exe chmod +x "$osUpdateExtendLoc"
addConf -a "extend osupdate $osUpdateExtendLoc" "$toolConfig"
exe service snmpd restart
}
osUpdateExtendLoc="${toolConfigLoc}/osupdate"
step_23_info() { echo "Create cron job for periodical (every 8 hours) apt-get update"; }
step_23() {
addConf -s "$osUpdateCronContent" "$osUpdateCron"
}
osUpdateCron="/etc/cron.d/aptUpdate"
osUpdateCronContent="22 */6 * * * root /usr/bin/apt-get -qq update"
step_25_info() { echo "Prepare nginx to provide php-fpm status to $toolName"; }
step_25_alias() { ALIAS="phpfpm"; }
step_25() {
echo -e "\n [!] Please add the following to your default server:\n"
echo "$phpFpmStatusNginx"
echo
if [ $QUIET -ne 0 ] ; then
answer=n
else
exe read -p "Open new shell to configure y/[n]? " answer
fi
case $answer in
[yY])
echoseq " [I] Opening interactive shell. Type \"exit\" to return to this script."
exe bash -i
echoseq " [I] Interactive shell ended. Continuing with $0."
exe nginx -t
endReturn -o $? "Nginx configuration error"
exe service nginx restart
;;
*)
;;
esac
}
# TODO error when no php is installed
phpVersionStr="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')"
phpFpmStatusNginx="# Provide php-fpm status
location ~ ^/(status|ping)\$ {
access_log off;
allow 127.0.0.1;
allow ::1;
deny all;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/php/php${phpVersionStr}-fpm.sock;
}"
step_26_info() { echo "Prepare php config for php-fpm status"; }
step_26_alias() { ALIAS="phpfpm_config"; }
step_26() {
exe sed -i "s/^;\(pm\.status_path\)/\1/" "$phpPoolConfigLoc"
exe php-fpm${phpVersionStr} -t
endReturn -o $? "Invalid php configuration"
service php${phpVersionStr}-fpm restart
}
phpConfigDir="/etc/php/${phpVersionStr}"
phpPoolConfigLoc="${phpConfigDir}/fpm/pool.d/www.conf"
step_27_info() { echo "Extend $toolName with parsing of php-fpm status"; }
step_27_alias() { ALIAS="phpfpm_extend"; }
step_27() {
checkExtend phpfpmsp
if [ "$?" != "0" ]; then
return 1
fi
exe wget https://github.com/librenms/librenms-agent/raw/master/snmp/phpfpmsp -O "${phpfpmExtendLoc}"
endReturn -o $? "Download failed"
exe chmod +x "$phpfpmExtendLoc"
addConf -a "extend phpfpmsp ${phpfpmExtendLoc}" "$toolConfig"
exe service snmpd restart
}
phpfpmExtendLoc="${toolConfigLoc}/phpfpmsp"
step_29_info() { echo "Prepare nginx to provide status to $toolName"; }
step_29_alias() { ALIAS="nginx"; }
step_29() {
echoseq -e "\n [!] Please add the following to your default server:\n"
echoseq "$nginxStatus"
echoseq
if [ $QUIET -ne 0 ] ; then
answer=n
else
exe read -p "Open new shell to configure y/[n]? " answer
fi
case $answer in
[yY])
echoseq " [I] Opening interactive shell. Type \"exit\" to return to this script."
exe bash -i
echoseq " [I] Interactive shell ended. Continuing with $0."
exe nginx -t
endReturn -o $? "Nginx configuration error"
exe service nginx restart
;;
*)
;;
esac
}
nginxStatus="# Provide nginx status
location /nginx-status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow ::1;
deny all;
}
"
step_30_info() { echo "Extend $toolName with parsing of nginx status"; }
step_30_alias() { ALIAS="nginx_extend"; }
step_30() {
checkExtend nginx
if [ "$?" != "0" ]; then
return 1
fi
exe wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/nginx -O "${nginxExtendLoc}"
endReturn -o $? "Download failed"
exe chmod +x "$nginxExtendLoc"
addConf -a "extend nginx ${nginxExtendLoc}" "$toolConfig"
exe service snmpd restart
}
nginxExtendLoc="${toolConfigLoc}/nginx"
# postfix
step_32_info() { echo "Extend for postfix detailed and queue"; }
step_32_alias() { ALIAS="postfix"; }
step_32() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe wget https://github.com/librenms/librenms-agent/raw/master/snmp/postfix-queues -O "${postfixQueuesExtendLoc}"
endReturn -o $? "Download postfix-queues failed"
exe wget https://github.com/librenms/librenms-agent/raw/master/snmp/postfixdetailed -O "${postfixScript}"
endReturn -o $? "Download postfixdetailed failed"
exe chmod +x "${postfixQueuesExtendLoc}"
exe chmod +x "${postfixScript}"
exe apt install $postfixDeps $aptOpt
}
postfixDeps="pflogsumm"
step_33_info() { echo "Prepare cache folder for postfixdetailed"; }
step_33() {
exe touch "$postfixCacheLoc"
exe chown root:$toolSysUser "$postfixCacheLoc"
exe chmod 770 "$postfixCacheLoc"
echoseq " [I] Create symlink /var/log/maillog which is used by postfixdetailed"
exe ln -fs /var/log/mail.log /var/log/maillog
echoseq " [I] Run /etc/snmp/postfixdetailed to create the initial cache file"
echoseq " so you don't end up with some crazy initial starting value."
exe sudo -u $toolSysUser "$postfixScript"
}
postfixCacheLoc="/var/cache/postfixdetailed"
postfixScript="${toolConfigLoc}/postfixdetailed"
postfixQueuesExtendLoc="${toolConfigLoc}/postfix-queues"
step_34_info() { echo "Create sudoers file for postfix scripts"; }
step_34() {
addConf -s "$postfixSudoersContent" "$postfixSudoersLoc"
echoseq " [I] Changing ${postfixQueuesExtendLoc} to add sudo for qshape"
exe sed -i -E "s/\`qshape/\`sudo qshape/" "${postfixQueuesExtendLoc}"
echoseq " [W] Reboot may be required to make these changes active"
}
postfixSudoersLoc="/etc/sudoers.d/snmppostfix"
postfixSudoersContent="${toolSysUser} ALL=(ALL) NOPASSWD: /usr/sbin/qshape"
step_35_info() { echo "Create postfix extends (postfixdetailed and postfix-queues)"; }
step_35() {
checkExtend postfix-queues
if [ $? -eq 0 ]; then
echoseq " [I] Create postfix-queues extend"
addConf -a "extend mailq ${postfixQueuesExtendLoc}" "$toolConfig"
fi
checkExtend postfixdetailed
if [ $? -eq 0 ]; then
echoseq " [I] Create postfixdetailed extend"
addConf -a "extend postfixdetailed ${postfixScript}" "$toolConfig"
fi
exe service snmpd restart
}
#fail2ban
step_37_info() { echo "Extend for fail2ban jail information"; }
step_37_alias() { ALIAS="fail2ban"; }
step_37(){
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe wget https://github.com/librenms/librenms-agent/raw/master/snmp/fail2ban -O "${fail2banExtendLoc}"
endReturn -o $? "Download postfix failed"
exe chmod +x "$fail2banExtendLoc"
checkExtend fail2ban
if [ $? -eq 0 ]; then
echoseq " [I] Create fail2ban extend"
addConf -a "extend fail2ban ${fail2banExtendLoc} -c" "$toolConfig"
fi
exe apt install $fail2banDeps $aptOpt
}
fail2banDeps="libjson-perl"
fail2banExtendLoc="${toolConfigLoc}/fail2ban"
step_38_info() { echo "Create cron to update fail2ban cache"; }
step_38() {
addConf -s "$fail2banCron" "$fail2banCronLoc"
}
fail2banCronLoc="/etc/cron.d/fail2banCache"
fail2banCron="# Update cache for faster fail2ban polling
*/3 * * * * root ${fail2banExtendLoc} -u"
step_40_info() { echo "Create linux distribution detection extend (distro)"; }
step_40_alias() { ALIAS="distro"; }
step_40() {
checkExtend distro
if [ $? -ne 0 ]; then
return 0
fi
exe wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/distro -O "${distroExtendLoc}"
endReturn -o $? "Download distro detection script failed"
exe chmod +x "$distroExtendLoc"
echoseq " [I] Create distro extend"
addConf -a "extend distro ${distroExtendLoc}" "$toolConfig"
exe service snmpd restart
}
distroExtendLoc="${toolConfigLoc}/distro"
step_42_info() {
echo "Gather dhcp information from a dhcpd lease file"
echoinfo "pi-hole lease file not supported"
}
step_42_alias() { ALIAS="dhcp"; }
step_42() {
local locExtName="dhcpstats"
local locExtUrl="https://github.com/librenms/librenms-agent/raw/master/snmp/dhcp.py"
local locExtLoc="${toolConfigLoc}/dhcp.py"
checkExtend $locExtName
[ $? -ne 0 ] && return 0
exe apt install dhcpd-pools
endReturn -o $? "Install dhcpd-pools failed"
exe wget $locExtUrl -O "${locExtLoc}"
endReturn -o $? "Download $locExtName script failed"
exe chmod +x "$locExtLoc"
echoseq " [I] Create extend for $locExtName"
addConf -a "extend $locExtName ${locExtLoc}" "$toolConfig"
echoseq " [I] Create config for $locExtName"
addConf -s "$dhcpExtendConfig" "$dhcpExtendConfigLoc"
echo " [W] Adapt config $dhcpExtendConfigLoc manually and restart snmpd"
}
dhcpExtendConfigLoc="${toolConfigLoc}/dhcp.json"
dhcpExtendConfig="{\"leasefile\": \"/var/lib/dhcp/dhcpd.leases\"
}"
step_44_info() { echo "Extend unbound stats"; }
step_44_alias() { ALIAS="unbound"; }
step_44() {
local locExtName="unbound"
local locExtUrl="https://github.com/librenms/librenms-agent/raw/master/snmp/unbound"
local locExtLoc="${toolConfigLoc}/unbound"
checkExtend $locExtName
[ $? -ne 0 ] && return 0
exe wget $locExtUrl -O "${locExtLoc}"
endReturn -o $? "Download $locExtName script failed"
exe chmod +x "$locExtLoc"
echoseq " [I] Create extend for $locExtName"
addConf -a "extend $locExtName /usr/bin/sudo ${locExtLoc}" "$toolConfig"
echoseq " [I] Create config for $locExtName"
addConf -s "$unboundExtendConfig" "$unboundExtendConfigLoc"
exe systemctl restart unbound.service
exe systemctl restart snmpd.service
}
unboundExtendConfigLoc="/etc/unbound/unbound.conf.d/extended-stats.conf"
unboundExtendConfig=$(cat <<UB_EOF
# Enable extended statistics
server:
extended-statistics: yes
statistics-cumulative: yes
remote-control:
control-enable: yes
control-interface: 127.0.0.1
UB_EOF
)
step_45_info() { echo "Set sudoers file to execute unbount-control"; }
step_45() {
addConf -s "$unboundSudoer" "$unboundSudoerLoc"
}
unboundSudoerLoc="/etc/sudoers.d/snmpunbound"
unboundSudoer="Debian-snmp ALL=(ALL) NOPASSWD: /usr/sbin/unbound-control, ${toolConfigLoc}/unbound"
step_46_info() { echo "Extend pi-hole stats"; }
step_46_alias() { ALIAS="pihole"; }
step_46() {
local locExtName="pi-hole"
local locExtUrl="https://github.com/librenms/librenms-agent/raw/master/snmp/pi-hole"
local locExtLoc="${toolConfigLoc}/pi-hole"
checkExtend $locExtName
[ $? -ne 0 ] && return 0
exe apt install $piHoleDeps $APTOPT
exe wget $locExtUrl -O "${locExtLoc}"
endReturn -o $? "Download $locExtName script failed"
exe chmod +x "$locExtLoc"
echoseq " [I] Create extend for $locExtName"
addConf -a "extend $locExtName ${locExtLoc}" "$toolConfig"
if [ $QUIET -ne 0 ]; then
outColor red
echo -e " [W] Check the following in the extend script and restart snmpd:\n"
else
echo " [I] Check the follwing in the extend script:"
fi
echo "(API_AUTH_KEY) Add your pi-hole API key"
echo " (API_URL) and check the API URL"
outColor
if [ $QUIET -eq 0 ]; then
exe read -p "Hit Enter to continue..."
exe vi "$locExtLoc"
exe systemctl restart snmpd.service
fi
}
piholeDeps="jq"
step_100_info() { echo "Notes"; }
step_100_alias() { ALIAS="notes"; }
step_100() {
outColor green
cat <<NOTES_END
# Reduce log level of snmpd
systemctl edit snmpd.service
[Service]
ExecStart=
ExecStart=/usr/sbin/snmpd -LSwd -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf -f -p /run/snmpd.pid
## Extract of loggin options from man page
LOGGING OPTIONS
The mechanism and destination to use for logging of warning and error messages can be controlled by passing various parameters to the -L flag.
-Le
Log messages to the standard error stream.
-Lf FILE
Log messages to the specified file.
-Lo
Log messages to the standard output stream.
-Ls FACILITY
Log messages via syslog, using the specified facility ('d' for LOG_DAEMON, 'u' for LOG_USER, or '0'-'7' for LOG_LOCAL0 through LOG_LOCAL7).
There are also "upper case" versions of each of these options, which allow the corresponding logging mechanism to be restricted to certain priorities of message. Using standard error logging as an example:
-LE pri
will log messages of priority 'pri' and above to standard error.
-LE p1-p2
will log messages with priority between 'p1' and 'p2' (inclusive) to standard error.
For -LF and -LS the priority specification comes before the file or facility token. The priorities recognised are:
0 or ! for LOG_EMERG,
1 or a for LOG_ALERT,
2 or c for LOG_CRIT,
3 or e for LOG_ERR,
4 or w for LOG_WARNING,
5 or n for LOG_NOTICE,
6 or i for LOG_INFO, and
7 or d for LOG_DEBUG.
NOTES_END
}
checkExtend() {
# adding dry run output for clarification
if [ $DRY -ne 0 ] ; then
echoseq " [I] check if \"extend ${1}\" exists..dry-run"
fi
exep "cat \"$toolConfig\" | grep -e '^\s*extend\s\+${1}' >>/dev/null 2>&1"
# Only warn if entry exists and dry-run is not seleted
if [ $? -eq 0 ] && [ $DRY -eq 0 ] ; then
return 1
fi
return 0
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh