├── README.md ├── check_unifi-controller.sh └── unifi.cfg /README.md: -------------------------------------------------------------------------------- 1 | ## Features 2 | * Shows device's state (up, down, upgrading, provisioning, etc.) 3 | * Shows how much clients are connected 4 | * Shows device's load 5 | * Shows firmware as well as whetcher newer firmware is avaiable and displays that 6 | * Shows controller's version 7 | * Manual status-mapping (e.g. should newer firmware trigger a warning?) 8 | * Multi-site support / autodetection 9 | 10 | 11 | ## What's different? 12 | * This script was forked from https://github.com/qgmgit/qgm-check_unifi. Main goal was to fetch more from the UniFi API and simplify the installation procedure. 13 | * Needed API functions from the external file were merged into the script file. 14 | * Optimized the parsing process **(0m:18s vs 1m:45s for 167 devices on demo.unifi.com)** 15 | * The Check_MK's service name is now mapped with UniFi_ which may be a problem when using one name twice (e.g. on two sites) 16 | * Permission checking of the config file to keep the credentials safe 17 | 18 | ## Requirements 19 | * UniFi Controller Software (can also be on remote host) 20 | * Check_MK Agent 21 | * Packages: jq, curl, wget 22 | 23 | ## Installation / Setup 24 | 25 | ### One-liner 26 | The I-am-lazy-just-install method: Just copy-paste the whole block in the shell on Debian-based systems 27 | ``` 28 | apt install jq curl wget -y \ 29 | && CMK_LOCAL=/usr/lib/check_mk_agent/local/check_unifi-controller.sh \ 30 | && CMK_CONFIG=/etc/check_mk/unifi.cfg \ 31 | && wget https://raw.githubusercontent.com/binarybear-de/cmk_check_unifi-controller/master/check_unifi-controller.sh -O $CMK_LOCAL \ 32 | && chmod +x $CMK_LOCAL \ 33 | && wget https://raw.githubusercontent.com/binarybear-de/cmk_check_unifi-controller/master/unifi.cfg -O $CMK_CONFIG \ 34 | && chmod 700 $CMK_CONFIG \ 35 | && chown root: $CMK_CONFIG \ 36 | && unset CMK_LOCAL CMK_CONFIG 37 | ``` 38 | 39 | ### updating 40 | ``` 41 | CMK_LOCAL=/usr/lib/check_mk_agent/local/check_unifi-controller.sh \ 42 | && wget https://raw.githubusercontent.com/binarybear-de/cmk_check_unifi-controller/master/check_unifi-controller.sh -O $CMK_LOCAL \ 43 | && chmod +x $CMK_LOCAL \ 44 | && unset CMK_LOCAL 45 | ``` 46 | 47 | ### manual 48 | * Install the packages "jq, curl, wget" 49 | * Move the ```check_unifi-controller.sh``` into the local dir ```/usr/lib/check_mk_agent/local``` 50 | * Move the ```unifi.cfg``` config file into Check_MK's config dir ```/etc/check_mk/unifi.cfg``` 51 | * Set permissions of ```unifi.cfg``` to 700 with owner root 52 | 53 | ### setup 54 | * Ideally create a read-only user in UniFi for this task. Following permissions should be given: 55 | * Allow read only access to all sites (if used with multisite) 56 | * Allow system stats access 57 | * Show pending devices (to show new devices in monitoring) 58 | * Set your credentials, controller's ip and other parameters in ```unifi.cfg``` 59 | 60 | ### Sample Output 61 | 62 | Running the script should give you something like this: 63 | ``` 64 | 0 UniFi-Controller - Build atag_5.11.39_12706, Check-Script version 2020-12-26 65 | 0 UniFi_SW-24 clients=31|load=1.05 CONNECTED, Site: office, Clients: 31, Firmware: 4.0.45.10545 (4.3.20.11298 avaible) 66 | 2 UniFi_AP-C clients=6|load=0.40 DISCONNECTED, Site: office, Clients: 6, Firmware: 4.0.45.10545 (4.3.20.11298 avaible) 67 | 0 UniFi_Gateway clients=0|load=null UPGRADING, Site: office, Clients: 0, Firmware: 4.4.51.5287926 68 | 0 UniFi_AP-A clients=6|load=0.40 CONNECTED, Site: office, Clients: 6, Firmware: 4.3.20.11298 avaible 69 | 0 UniFi-Devices devices=6|sites=1|unamed=0|unadopted=0 6 devices on 1 sites 70 | ``` 71 | -------------------------------------------------------------------------------- /check_unifi-controller.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # script to list all UniFi devices from the given controller and get some infos 3 | # https://github.com/binarybear-de/cmk_check_unifi-controller 4 | SCRIPTBUILD="BUILD 2021-11-04-v3" 5 | 6 | ############################################################### 7 | # you should not need to edit anything here - use the config file! 8 | ############################################################### 9 | 10 | CONFIG_FILE=/etc/check_mk/unifi.cfg 11 | CONFIG_ACCESS=$(stat -c %a $CONFIG_FILE) 12 | CONFIG_OWNER=$(stat -c %U $CONFIG_FILE) 13 | 14 | if [ ! $CONFIG_ACCESS = 700 ] || [ ! $CONFIG_OWNER = root ] ; then 15 | echo "2 UniFi-Controller - Config permission mismatch, must be 700 with owner root (current: $CONFIG_ACCESS, owner $CONFIG_OWNER)!" 16 | exit 1 17 | fi 18 | 19 | # source the settings from file 20 | . $CONFIG_FILE 21 | 22 | # init counters and variables 23 | NUM_NOTNAMED=0 24 | NUM_NOTADOPTED=0 25 | STATUS=0 26 | 27 | # create the temporary files 28 | COOKIE_FILE=/tmp/unifi-check-cookie 29 | 30 | #the curl command used to pull the data from the WebUI 31 | CURL_CMD="curl --silent --cookie ${COOKIE_FILE} --cookie-jar ${COOKIE_FILE} $CURLOPTS" 32 | 33 | getDeviceInfo() { 34 | echo $DEVICES | jq " .data | .[] | select(.serial | contains($1))" 35 | } 36 | getValueFromDevice() { 37 | # read value, replace spaces with underscores and strip quotes (see issue #7) 38 | echo $JSON | jq " .$1 " | sed -e 's/ /_/g' | sed -e 's/"//g' 39 | } 40 | getValueFromController() { 41 | echo $JSON | jq ".data | .[] | .$1" | sed -e 's/"//g' 42 | } 43 | 44 | loginController() { 45 | touch $COOKIE_FILE 46 | chmod 600 $COOKIE_FILE 47 | if ! $(${CURL_CMD} --data "{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}" $BASEURL/api/login > /dev/null) ; then 48 | echo "2 UniFi-Controller - Controller unavailable! Login failed or no route to API!" 49 | exit 1 50 | fi 51 | } 52 | 53 | 54 | ############################################################### 55 | # block 1: login to controller and get some controller status 56 | ############################################################### 57 | 58 | # check if there's an existing login cookie - else try to login interactively 59 | if [ ! -e "$COOKIE_FILE" ]; then 60 | loginController 61 | fi 62 | 63 | # get some basic information about the controller - if this fails the cookie may has expired. Then deleting cookie, login again and try again (UGLY) 64 | JSON=$(${CURL_CMD} $BASEURL/api/s/default/stat/sysinfo) 65 | if [[ "$JSON" = *"LoginRequired"* ]]; then 66 | rm $COOKIE_FILE 67 | loginController 68 | JSON=$(${CURL_CMD} $BASEURL/api/s/default/stat/sysinfo) 69 | fi 70 | 71 | if [ "$(getValueFromController update_available)" = "true" ]; then 72 | BUILD="$BUILD (Update avaiable!)" 73 | STATUS=$STATUS_UPGRADABLE 74 | fi 75 | 76 | #output the controllers version 77 | echo "$STATUS UniFi-Controller - Hostname: $(getValueFromController hostname), Build $(getValueFromController build), Check-Script $SCRIPTBUILD" 78 | 79 | ############################################################### 80 | # block 2: get every site's configuration 81 | ############################################################### 82 | 83 | # get a list of all sites on the controller 84 | SITES=$(echo $(${CURL_CMD} $BASEURL/api/self/sites) | jq '.data | .[] | .name' | sed -e 's/"//g') 85 | 86 | # loop over all sites 87 | for SITE in $SITES; do 88 | 89 | # counter of sites 90 | ((NUM_SITES=NUM_SITES+1)) 91 | 92 | # get all info of all devices of that site as json 93 | DEVICES=$(${CURL_CMD} --data "{}" $BASEURL/api/s/$SITE/stat/device) 94 | 95 | # loop over all serial numbers (devices) on current site 96 | for SERIAL in $(echo $DEVICES | jq '.data | .[] | .serial'); do 97 | 98 | # select one device 99 | JSON=$(getDeviceInfo $SERIAL) 100 | 101 | # check if the device is already adopted. if not: set controller's state to warning and skip to next device 102 | if [ "$(getValueFromDevice adopted)" = "false" ]; then 103 | ((NUM_NOTADOPTED=NUM_NOTADOPTED+1)) 104 | break 105 | fi 106 | 107 | # increment device counter - only if device is adopted! 108 | ((NUM_DEVICES=NUM_DEVICES+1)) 109 | 110 | # check if the device is 'null' which means it is not named at all and skip to next device 111 | DEVICE_NAME=$(getValueFromDevice name) 112 | if [ "$DEVICE_NAME" = "null" ]; then 113 | ((NUM_NOTNAMED=NUM_NOTNAMED+1)) 114 | break 115 | fi 116 | # if named and adopted, get more info 117 | 118 | CLIENTS=$(getValueFromDevice num_sta) 119 | UPGRADEABLEFW=$(getValueFromDevice upgrade_to_firmware) 120 | VERSION=$(getValueFromDevice version) 121 | STATE=$(getValueFromDevice state) 122 | SCORE=$(getValueFromDevice satisfaction) 123 | LOCATING=$(getValueFromDevice locating) 124 | STATUS=3 # set the service-state in check_mk, default is unknown if something weird happens 125 | 126 | # determining the device's state 127 | # https://community.ui.com/questions/Fetching-current-UAP-status/88a197f9-3530-4580-8f0b-eca43b41ba6b 128 | case $STATE in 129 | 1) STATUS=0 130 | DESCRIPTION="CONNECTED";; 131 | 132 | 0) STATUS=2 133 | DESCRIPTION="DISCONNECTED!";; 134 | 135 | 4) STATUS=$STATUS_UPGRADING 136 | DESCRIPTION="UPGRADING";; 137 | 138 | 5) STATUS=$STATUS_PROVISIONING 139 | DESCRIPTION="PROVISIONING";; 140 | 141 | 6) STATUS=$STATUS_HEARTBEAT_MISSED 142 | DESCRIPTION="heartbeat missed!";; 143 | 144 | 10) STATUS=2 145 | DESCRIPTION="Adoption failed!";; 146 | 147 | *) DESCRIPTION="Unkown state ($STATE)!";; 148 | esac 149 | 150 | # make a upgrade check 151 | if [ "$UPGRADEABLEFW" != "$VERSION" ] && [ "$UPGRADEABLEFW" != "null" ]; then 152 | VERSION="$VERSION ($UPGRADEABLEFW avaible)" 153 | # check if status is "better" than upgradable. Prevent a previous CRIT event to be reduced to WARN simply because device is upgradable... 154 | if [ $STATUS -le $STATUS_UPGRADABLE ]; then STATUS=$STATUS_UPGRADABLE; fi 155 | fi 156 | if [ "$LOCATING" = "true" ]; then 157 | LOCATOR="Locator is enabled!" 158 | STATE=1 159 | fi 160 | # final output per device including infos and metrics 161 | if [ "$USE_SITE_PREFIX" = "1" ]; then 162 | echo "$STATUS UniFi_$SITE-$DEVICE_NAME clients=$CLIENTS|score=$SCORE;;;-10;100 $DESCRIPTION, Site: $SITE, Clients: $CLIENTS, Firmware: $VERSION" 163 | else 164 | echo "$STATUS UniFi_$DEVICE_NAME clients=$CLIENTS|score=$SCORE;;;-10;100 $DESCRIPTION, Site: $SITE, Clients: $CLIENTS, Firmware: $VERSION" 165 | fi 166 | done 167 | done 168 | 169 | ############################################################### 170 | # block 3: summary of all devices 171 | ############################################################### 172 | 173 | if [ "$NUM_NOTADOPTED" -eq 0 ] && [ "$NUM_NOTNAMED" -eq 0 ]; then 174 | echo "0 UniFi-Devices devices=$NUM_DEVICES|sites=$NUM_SITES|unamed=$NUM_NOTNAMED|unadopted=$NUM_NOTADOPTED $NUM_DEVICES devices on $NUM_SITES sites - no unnamed or unadopted devices found" 175 | else 176 | NUM_NOTADOPTED=$((NUM_NOTADOPTED/NUM_SITES)) 177 | echo "1 UniFi-Devices devices=$NUM_DEVICES|sites=$NUM_SITES|unamed=$NUM_NOTNAMED|unadopted=$NUM_NOTADOPTED $NUM_DEVICES devices on $NUM_SITES sites - found $NUM_NOTNAMED unnamed devices and $NUM_NOTADOPTED unadopted devices!" 178 | fi 179 | 180 | ############################################################### 181 | -------------------------------------------------------------------------------- /unifi.cfg: -------------------------------------------------------------------------------- 1 | # script to list all UniFi devices from the given controller and get some infos https://github.com/binarybear-de/cmk_check_unifi-controller 2 | # needs to be placed in /etc/check_mk as unifi.cfg by default 3 | 4 | # Settings for the controller-binding 5 | USERNAME="someuser" 6 | PASSWORD="somepass" 7 | BASEURL=https://demo.ui.com 8 | 9 | # additional curl options 10 | # - insecure-flag is needed if a self-signed certificate is used and is not imported in linux - usually okay if controller is running locally 11 | # - enforce a specific version of TLS 12 | CURLOPTS="--insecure --tlsv1.2 -H \"Content-Type: application/json\"" 13 | 14 | # mapping of device's states to check_mk statuses 15 | # STATUS: 0 = OK, 1 = WARN, 2 = CRIT, 3 = UNKN 16 | STATUS_PROVISIONING=1 17 | STATUS_UPGRADING=1 18 | STATUS_UPGRADABLE=0 19 | STATUS_HEARTBEAT_MISSED=1 20 | STATUS_NOBACKUP=1 21 | 22 | # adds site name in the checkmk service per device to allow multiple names with same name on different sites 23 | USE_SITE_PREFIX=0 24 | --------------------------------------------------------------------------------