#!/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" seq_config() { ## Apt cmdline option to suppress user interaction quiet && APTOPT="-y" ## Return of non zero value will abort the sequence return 0 } step_1_info() { echo "Install packages for $toolName"; } step_1_alias() { echo "install"; } step_1() { exe apt update if quiet; 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() { echo "v3access"; } step_2() { # ## Create authentication entry exep "cat \"$v3AuthLoc\" | grep -e '^\s*usmUser'" if [ "$?" == "0" ]; then info exe read -p "User entry found. Continue: y/n(default)? " answer case $answer in [yY]) info info "Continuing installation..." ;; *) info info "Installation aborted" return 1; ;; esac fi read -p "SNMPv3 Username: " v3User read -p "SNMPv3 Password: " v3Pass info read -p "Repeat Password: " v3Pass2 if [ "$v3Pass" != "$v3Pass2" ] ; then error -e "Password mismatch" return 1 fi info 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 [ -n "${1:-}" ] && [ "$1" == "-s" ] ; then info "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 ): " 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() { echo "ufw"; } step_5() { shift local lInterface="eth0" [ -n "${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() { echo "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() { echo "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() { echo "phpfpm"; } step_25() { echo -e "\n [!] Please add the following to your default server:\n" echo "$phpFpmStatusNginx" echo if quiet ; then answer=n else exe read -p "Open new shell to configure y/[n]? " answer fi case $answer in [yY]) info "Opening interactive shell. Type \"exit\" to return to this script." exe bash -i info "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() { echo "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() { echo "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() { echo "nginx"; } step_29() { info -e "\n [!] Please add the following to your default server:\n" info "$nginxStatus" info if quiet ; then answer=n else exe read -p "Open new shell to configure y/[n]? " answer fi case $answer in [yY]) info "Opening interactive shell. Type \"exit\" to return to this script." exe bash -i info "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() { echo "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() { echo "postfix"; } step_32() { local aptOpt= if quiet;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" info "Create symlink /var/log/maillog which is used by postfixdetailed" exe ln -fs /var/log/mail.log /var/log/maillog info "Run /etc/snmp/postfixdetailed to create the initial cache file" info " 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" info "Changing ${postfixQueuesExtendLoc} to add sudo for qshape" exe sed -i -E "s/\`qshape/\`sudo qshape/" "${postfixQueuesExtendLoc}" warning "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 info "Create postfix-queues extend" addConf -a "extend mailq ${postfixQueuesExtendLoc}" "$toolConfig" fi checkExtend postfixdetailed if [ $? -eq 0 ]; then info "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() { echo "fail2ban"; } step_37(){ local aptOpt= if quiet;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 info "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() { echo "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" info "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() { echo "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" info "Create extend for $locExtName" addConf -a "extend $locExtName ${locExtLoc}" "$toolConfig" info "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() { echo "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" info "Create extend for $locExtName" addConf -a "extend $locExtName /usr/bin/sudo ${locExtLoc}" "$toolConfig" info "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 <>/dev/null 2>&1" # Only warn if entry exists and dry-run is not seleted if [ $? -eq 0 ] && ! dry ; then return 1 fi return 0 } readonly sqr_minVersion=16 . /usr/local/bin/sequencer.sh