Commit 9ef09759 authored by Peter Möller's avatar Peter Möller
Browse files

Update linux/host-monitor.sh

parents
#!/bin/bash
# Collecting host data and sending it to the CS monitor server
# Linux version
# 2021-06-02/PM
MONITOR_RESTAPI_URL=https://monitor.cs.lth.se/api/v1
source /opt/monitoring/host-monitor.template
# 1. Generating data
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# sysinfo
# Operating System (OS='Ubuntu 20.04.1 LTS'):
# Find out distro
# Fist: look at the /etc/*-release files
OS="$(less $(ls -1 /etc/mageia-release /etc/centos-release /etc/redhat-release /etc/gentoo-release /etc/fedora-release 2>/dev/null | head -1) 2>/dev/null)"
# If no such file, look for /etc/os-release
if [ -z "$OS" ]; then
[[ -f /etc/os-release ]] && OS="$(less /etc/os-release | grep PRETTY_NAME | cut -d\" -f2)"
fi
# If no such file, look for /etc/lsb-release
if [ -z "$OS" ]; then
[[ -f /etc/lsb-release ]] && OS="$(less /etc/os-release | grep DISTRIB_DESCRIPTION | cut -d\" -f2)"
fi
# If no such file, look for /proc/version
if [ -z "$OS" ]; then
[[ -f /proc/version ]] && OS="$(less /proc/version | cut -d\( -f1)"
fi
# OK, so it an unknown system
if [ -z "$OS" ]; then
OS="Unknown Linux-distro"
fi
##OS="$(lsb_release -ds)"
# Kind of CPU (CPUModel='Intel® Xeon® CPU E5-2680 v4 @ 2.40GHz'):
CPUModel="$(egrep "^model name" /proc/cpuinfo | sort -u | cut -d: -f2 | sed -e 's/^ //' -e 's/(R)/®/g')"
# Number of CPU:s (NbrCPUs=2):
NbrCPUs=$(egrep "^processor" /proc/cpuinfo | wc -l)
# Size of memory [kB]
#RAM=$(egrep "^MemTotal" /proc/meminfo | awk '{print $2}')
RAM=$(/usr/sbin/dmidecode -t 17 | grep "Size.*MB" | awk '{s+=$2} END {print s * 1024}') # Ex: RAM=4194304
# Kind of memory (ECC='No ECC' or ECC='Multi-bit ECC'):
ECC="$(/usr/sbin/dmidecode -t memory | egrep "Error Correction Type" | sort -u | cut -d: -f2 | sed -e 's/^ //' -e 's/None/No ECC/')"
# What kind of authentication? Ex: Authentication=Lucat
Authentication="$(if [ -n "$(egrep -v "#|^$" /etc/pam.d/common-account | egrep pam_krb5.so)" -a -n "$(egrep "default_realm = UW.LU.SE" /etc/krb5.conf)" ]; then echo Lucat; else echo Standalone; fi)"
AuthStr="\"authentication\": \"${Authentication}\"" # Ex: AuthStr='"authentication": "Lucat"'
# Firewall. Ex: Firewall=ufw
Firewall="$(systemctl list-units --type=service --state=active | egrep -i "^\ *(iptables|firewalld|ufw)" | awk '{print $1}' | cut -d\. -f1)"
FirewWStr="\"firewall\":\"${Firewall}\"" # Ex: FirewWStr='"firewall":"ufw"'
# Disks
Filesystems="$(df -kT -t xfs -t ext4 | egrep "\/" | awk '{print $1" "$2" "$3" "$7}')"
# Ex: a number of rows with
# Filesystem Type 1K-blocks Mounted on
# /dev/mapper/vg0-ubuntu ext4 13343816 /
LVMDisks="$(LANG=C lsblk | egrep -i lvm | awk '{print $4" "$NF}' | egrep -vi swap | sort -u)"
# Ex:
# LVMDisks='13G /
# 500G /Websites
# 50G /var/log/apache2'
# Flags
# SELinux
SELinux="$(if sestatus &>/dev/null; then sestatus | egrep "^Current mode:" | awk '{print $NF}'; else echo "Not present"; fi)"
# CPU bugs
CPUBugs="$(egrep "^bugs" /proc/cpuinfo | cut -d: -f2 | cut -c2- | uniq)"
# Ex: CPUBugs='cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit'
Kernel="$(uname -r 2>/dev/null)" # Ex: Kernel=5.4.0-62-generic
Architecture="$(uname -m 2>/dev/null)" # Ex: Architecture=x86_64
# Are we in a Virtual environment? This one is a bit tricky since there are many ways to cover this.
# Read this for more info: http://unix.stackexchange.com/questions/89714/easy-way-to-determine-virtualization-technology
VMenv="$(dmesg 2>/dev/null | grep -i " Hypervisor detected: " 2>/dev/null | cut -d: -f2 | sed 's/^ *//')"
# Ex: VMenv='VMware'
if [ -z "${USER/root/}" -o -z "${UID/0/}" ]; then
# Get a better VMenv if found
if [ -n "$VMenv" ]; then
VMenv="$(/usr/sbin/dmidecode -s system-product-name 2>/dev/null)"
fi
# Ex: VMenv='VMware Virtual Platform'
# It may still be a VM environment
if [ -z "$VMenv" ]; then
VMenv="$(virt-what 2>/dev/null)"
# Ex: VMenv='vmware'
fi
if [ -z "$VMenv" ]; then
VMenv="$(if [ -n "$(grep "^flags.*\ hypervisor\ " /proc/cpuinfo)" ]; then echo "VM environment detected"; fi)"
# Ex: VMenv='VM environment detected'
fi
fi
# Get more platform data
PlatformManufacturer="$(/usr/sbin/dmidecode -t 2 2>/dev/null | egrep "^\s*Manufacturer:" | cut -d: -f2 | cut -c2-)" # Ex: PlatformManufacturer=LNVO
PlatformType="$(/usr/sbin/dmidecode -t 2 2>/dev/null | egrep "^\s*Type:" | cut -d: -f2 | cut -c2-)" # Ex: PlatformType=Motherboard
# Network interfaces
IFs=$(ip a |awk '/state UP/{print $2}' | sed 's/://')
# Ex: IFs='ens192
# br-8ebd54cbbafb
# veth079b7c8@if123'
# fail2ban
case $(systemctl status fail2ban &>/dev/null; echo $?) in
0) Fail2Ban="Active";;
1) Fail2Ban="Generic failure or unspecified error";;
2) Fail2Ban="Invalid or excess arguments";;
3) Fail2Ban="Unimplemented";;
4) Fail2Ban="Not installed";;
5) Fail2Ban="Not installed";;
6) Fail2Ban="Not configured";;
7) Fail2Ban="Not running";;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Security patches
SecurityPatches="$(apt-get update &>/dev/null && apt list --upgradable 2>/dev/null | egrep "\-security" | sed -e 's/\[upgradable from: //' -e 's/\]//' | tr '[/ ]' '\t')"
# List of: Package Channel CurrentVer Arch NewVersion
# intel-microcode focal-updates,focal-security,focal-updates,focal-security 3.20210216.0ubuntu0.20.04.1 amd64 3.20201110.0ubuntu0.20.04.2
# libhogweed5 focal-updates,focal-security,focal-updates,focal-security 3.5.1+really3.5.1-2ubuntu0.1 amd64 3.5.1+really3.5.1-2
# libmysqlclient21 focal-updates,focal-security,focal-updates,focal-security 8.0.25-0ubuntu0.20.04.1 amd64 8.0.22-0ubuntu0.20.04.3
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Listening ports
ListeningPorts="$(lsof +c 0 -i 4 -i 6 -n -P 2>/dev/null | grep LISTEN | awk '{print $1" "$3" "$5" "$8" "$9 }' | sed 's/\(.*\):/\1 /' | sort -u)"
# List of: Application User IPver Proto Servicerange Port
# apache2 root IPv6 TCP * 88
# apache2 www-data IPv6 TCP * 88
# cupsd root IPv4 TCP 127.0.0.1 631
# cupsd root IPv6 TCP [::1] 631
# dnsmasq nobody IPv4 TCP 127.0.1.1 53
# docker-proxy root IPv6 TCP * 4000
# dsmcad root IPv4 TCP * 1581
# dsmcad root IPv4 TCP * 2123
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Firewall -- No longer used as of 2021-05-28
FWrules="$(ufw status verbose 2>/dev/null | egrep "(ALLOW|DENY) IN" | awk '{print $1}' | cut -d\/ -f1 | egrep -vi "^anywhere|out" | tr ',' $'\n' | sort -nu)"
# Ex:
# FWrules='22
# 161
# 2500:5000
# 5666'
####################################################################################################################################################################
####################################################################################################################################################################
# 2. Generate JSON-parts
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# sysinfo
# Create a string for the CPU Bugs (to make the final assemble shorter)
CPUBugsStr="$(if [ -n "$CPUBugs" ]; then echo ", \"cpu-bugs:${CPUBugs// /\", \"cpu-bugs:}\""; fi)"
# Assemble the Flags string
Flags="\"selinux:$SELinux\", \"kernel:${Kernel}\"$CPUBugsStr, \"arch:${Architecture:---}\", \"fail2ban:$Fail2Ban\""
# partitions
OUTPUT=""
while read -r Filesystem Type Kblocks MountP
do
if [ -n "$(echo "$LVMDisks" | egrep "\s${MountP}$")" ]; then
LVM="LVM"
case $(echo "$LVMDisks" | egrep "\s${MountP}$" | awk '{print $1}' | sed 's/[0-9.]*//') in
M) ScaleFactor=1024;;
G) ScaleFactor=1048576;;
T) ScaleFactor=1073741824;;
esac
Kblocks=$(echo "scale=0; $(echo "$LVMDisks" | egrep "\s${MountP}$" | awk '{print $1}' | sed 's/[MGT]//') * $ScaleFactor" | bc -l)
else
LVM=""
fi
OUTPUT+="{ \"partition\": \"$Filesystem\", \"mount-point\":\"$MountP\", \"type\":\"$Type\", \"total-kb\":$Kblocks, \"storage\":\"${LVM:-direct}\" },"
done <<< "$Filesystems"
# Assemble the complete string (minus the final comma)
FilesystemStr="\"partitions\": [ ${OUTPUT%%,} ]"
# Network interfaces
OUTPUT=""
for iname in $IFs
do
IP4=$(ip -4 -o a show ${iname%%@if[0-9]*} | awk '{print $4}')
IP6=$(ip -6 -o a show ${iname%%@if[0-9]*} | awk '{print $4}')
MAC="$(ip link show dev ${iname%%@if[0-9]*} |awk '/link/{print $2}')"
MAC_P=$(ethtool -P ${iname%%@if[0-9]*} | awk '{print $NF}')
Speed="$(ethtool ${iname%%@if[0-9]*} | grep "Speed:" | awk '{print $NF}')"
OUTPUT+="{ \"interface\": \"$iname\", \"ip4\": \"${IP4}\", \"ip6\": \"${IP6}\", \"mac\": \"${MAC}\", \"mac-p\": \"${MAC_P}\", \"speed\": \"${Speed}\" },"
done
NIStr="\"network-interfaces\": [ $(echo "${OUTPUT}" | sed 's/,$//') ]"
# Ex: NIStr='"network-interfaces": [ { "interface": "ens192", "ip4": "130.235.16.11/23", "ip6": "fe80::250:56ff:feb6:b194/64", "mac": "00:50:56:b6:b1:94", "mac-p": "00:50:56:b6:b1:94", "speed": "10000Mb/s" } ]'
# Platform
if [ -n "$VMenv" ]; then
PlatformStr="\"platform\": { \"virtualized\": true, \"name\": \"$VMenv\" }"
else
PlatformStr="\"platform\": { \"virtualized\": false, \"name\": \"type:$PlatformType\" }"
fi
# network
AliasName=", \"alias\": [\"$DNSAlias\"] "
NetworkStr="\"network\": { \"hostname\": \"$(hostname -f)\"$AliasName }"
CPUstr="\"cpu\": { \"name\": \"${CPUModel:---}\", \"threads\": ${NbrCPUs:---} }"
RAMStr="\"memory\": { \"total-kb\": ${RAM:---}, \"type\": \"${ECC:---}\" }"
SysinfoStr="\"sysinfo\": { \"os\": \"${OS:---}\", \"authentication\":\"${Authentication}\", \"firewall\":\"${Firewall}\", \"flags\": [ ${Flags} ], $CPUstr, $RAMStr, $FilesystemStr, $NIStr, $PlatformStr, $NetworkStr }"
# Ex:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# listening ports
if [ -n "$ListeningPorts" ]; then
OUTPUT=""
while read -r line
do
read Application User IPver Proto Binding Port <<< "$line"
# Determine if there's some form of firewall rule that covers $Port:
FWrule="null"
if [ -n "$Firewall" ]; then
if [ -n "$(echo "$FWrules" | egrep "$Port")" ]; then
FWrule="true"
else
FWrule="false"
fi
fi
#OUTPUT+="{ \"binding\": \"${Binding:--}\", \"port\": ${Port:--}, \"process-owner\": \"${Application:--}\", \"process-user\": \"${User:--}\", \"IPver\": \"${IPver:--}\", \"protocol\": \"${Proto:--}\" },"
OUTPUT+="{ \"binding\": \"${Binding:--}\", \"port\": ${Port:--}, \"process-owner\": \"${Application:--}\", \"process-user\": \"${User:--}\", \"protocol\": \"${Proto:--}\", \"firewall-rule\": $FWrule },"
done <<< "$ListeningPorts"
# Assemble the complete string (minus the final comma)
ListenStr=", \"listen-ports\": [ ${OUTPUT%%,} ]"
else
ListenStr=""
fi
# Ex:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# security patches
if [ -n "$SecurityPatches" ]; then
OUTPUT=""
while read -r Package Sources InstalledVer Arch NewVer
do
Source="$(echo -e ${Sources//,/'\n'} | sort -u | sed -z 's/\n/,/g;s/,$/\n/')"
STR="\"${Sources//,/\",\"}\""
SourceArr="$(echo -e ${STR//,/'\n'} | sort -u | sed -z 's/\n/,/g;s/,$/\n/')"
OUTPUT+="{ \"installed-version\": \"$InstalledVer\", \"new-version\": \"$NewVer\", \"package\": \"$Package\", \"sources\": [ $SourceArr ] },"
done <<< "$SecurityPatches"
# Assemble the complete string (minus the final comma)
SecurityPatchStr=", \"security-patches\": [ ${OUTPUT%%,} ]"
else
SecurityPatchStr=""
fi
# Ex:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# firewall rules
#OUTPUT=""
#if [ -n "$FWrules" ]; then
#while read -r Rule Binding
#do
#if echo "$Rule" | egrep ":" &>/dev/null ; then
#OUTPUT+="{ \"binding\": \"${Binding:-*}\", \"port\": [$(echo $Rule | cut -d: -f1), $(echo $Rule | cut -d: -f2)] },"
#else
#OUTPUT+="{ \"binding\": \"${Binding:-*}\", \"port\": $Rule },"
#fi
#done <<< "$FWrules"
#FWrulesStr=", \"firewall-rules\": [ $(echo "$OUTPUT" | sed 's/,$//') ]"
#else
#FWrulesStr=""
#fi
# Ex:
# FWrulesStr=', "firewall-rules": [ { "binding": "*", "port": 22 },{ "binding": "*", "port": 161 },{ "binding": "*", "port": [2500, 5000] },{ "binding": "*", "port": 5666 } ]'
# 3. Build observation string and check for errors
OBSERVATIONS="{ ${SysinfoStr//\"--\"/null}${ListenStr//\"--\"/null}${SecurityPatchStr} }"
# 4. Upload results
curl --silent -X POST "$MONITOR_RESTAPI_URL/hosts/monitor?token=$SOURCE_TOKEN" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d "$OBSERVATIONS"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment