From 10e2e33a023f36d02511628e88d260e41adb41d3 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Wed, 22 Mar 2023 02:45:09 +0100 Subject: [PATCH] Setup: Update digitalocean check.sh and cleanup.sh scripts Signed-off-by: Michael Mayer --- setup/docker/cloud/digitalocean/check.sh | 208 +++++++-------------- setup/docker/cloud/digitalocean/cleanup.sh | 4 +- 2 files changed, 66 insertions(+), 146 deletions(-) diff --git a/setup/docker/cloud/digitalocean/check.sh b/setup/docker/cloud/digitalocean/check.sh index b389ba1f6..57e528506 100755 --- a/setup/docker/cloud/digitalocean/check.sh +++ b/setup/docker/cloud/digitalocean/check.sh @@ -1,10 +1,10 @@ #!/bin/bash # DigitalOcean Marketplace Image Validation Tool -# © 2021 DigitalOcean LLC. +# © 2021-2022 DigitalOcean LLC. # This code is licensed under Apache 2.0 license (see LICENSE.md for details) -VERSION="v. 1.6" +VERSION="v. 1.8.1" RUNDATE=$( date ) # Script should be run with SUDO @@ -31,6 +31,7 @@ cmdExists() { function getDistro { if [ -f /etc/os-release ]; then # freedesktop.org and systemd + # shellcheck disable=SC1091 . /etc/os-release OS=$NAME VER=$VERSION_ID @@ -40,6 +41,7 @@ elif type lsb_release >/dev/null 2>&1; then VER=$(lsb_release -sr) elif [ -f /etc/lsb-release ]; then # For some versions of Debian/Ubuntu without lsb_release command + # shellcheck disable=SC1091 . /etc/lsb-release OS=$DISTRIB_ID VER=$DISTRIB_RELEASE @@ -52,8 +54,8 @@ elif [ -f /etc/SuSe-release ]; then : elif [ -f /etc/redhat-release ]; then # Older Red Hat, CentOS, etc. - VER=$( cat /etc/redhat-release | cut -d" " -f3 | cut -d "." -f1) - d=$( cat /etc/redhat-release | cut -d" " -f1 | cut -d "." -f1) + VER=$(cut -d" " -f3 < /etc/redhat-release | cut -d "." -f1) + d=$(cut -d" " -f1 < /etc/redhat-release | cut -d "." -f1) if [[ $d == "CentOS" ]]; then OS="CentOS Linux" fi @@ -68,15 +70,16 @@ SHADOW=$(cat /etc/shadow) } function checkAgent { - # Check for the presence of the do-agent in the filesystem - if [ -d /var/opt/digitalocean/do-agent ];then - echo -en "\e[41m[FAIL]\e[0m DigitalOcean Monitoring Agent detected.\n" + # Check for the presence of the DO directory in the filesystem + if [ -d /opt/digitalocean ];then + echo -en "\e[41m[FAIL]\e[0m DigitalOcean directory detected.\n" ((FAIL++)) STATUS=2 if [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]] || [[ $OS == "AlmaLinux" ]]; then - echo "The agent can be removed with 'sudo yum remove do-agent' " - elif [[ $OS == "Ubuntu" ]]; then - echo "The agent can be removed with 'sudo apt-get purge do-agent' " + echo "To uninstall the agent: 'sudo yum remove droplet-agent'" + echo "To remove the DO directory: 'find /opt/digitalocean/ -type d -empty -delete'" + elif [[ $OS == "Ubuntu" ]] || [[ $OS == "Debian" ]]; then + echo "To uninstall the agent and remove the DO directory: 'sudo apt-get purge droplet-agent'" fi else echo -en "\e[32m[PASS]\e[0m DigitalOcean Monitoring agent was not found\n" @@ -90,8 +93,9 @@ function checkLogs { # Check if there are log archives or log files that have not been recently cleared. for f in /var/log/*-????????; do [[ -e $f ]] || break - if [ $f != $cp_ignore ]; then - echo -en "\e[93m[WARN]\e[0m Log archive ${f} found\n" + if [ "${f}" != "${cp_ignore}" ]; then + echo -en "\e[93m[WARN]\e[0m Log archive ${f} found; Contents:\n" + cat "${f}" ((WARN++)) if [[ $STATUS != 2 ]]; then STATUS=1 @@ -100,7 +104,8 @@ function checkLogs { done for f in /var/log/*.[0-9];do [[ -e $f ]] || break - echo -en "\e[93m[WARN]\e[0m Log archive ${f} found\n" + echo -en "\e[93m[WARN]\e[0m Log archive ${f} found; Contents:\n" + cat "${f}" ((WARN++)) if [[ $STATUS != 2 ]]; then STATUS=1 @@ -108,17 +113,19 @@ function checkLogs { done for f in /var/log/*.log; do [[ -e $f ]] || break - if [[ "${f}" = '/var/log/lfd.log' && "$( cat "${f}" | egrep -v '/var/log/messages has been reset| Watching /var/log/messages' | wc -c)" -gt 50 ]]; then - if [ $f != $cp_ignore ]; then - echo -en "\e[93m[WARN]\e[0m un-cleared log file, ${f} found\n" + if [[ "${f}" = '/var/log/lfd.log' && "$(grep -E -v '/var/log/messages has been reset| Watching /var/log/messages' "${f}" | wc -c)" -gt 50 ]]; then + if [ "${f}" != "${cp_ignore}" ]; then + echo -en "\e[93m[WARN]\e[0m un-cleared log file, ${f} found; Contents:\n" + cat "${f}" ((WARN++)) if [[ $STATUS != 2 ]]; then STATUS=1 fi fi - elif [[ "${f}" != '/var/log/lfd.log' && "$( cat "${f}" | wc -c)" -gt 50 ]]; then - if [ $f != $cp_ignore ]; then - echo -en "\e[93m[WARN]\e[0m un-cleared log file, ${f} found\n" + elif [[ "${f}" != '/var/log/lfd.log' && "$(wc -c < "${f}")" -gt 50 ]]; then + if [ "${f}" != "${cp_ignore}" ]; then + echo -en "\e[93m[WARN]\e[0m un-cleared log file, ${f} found; Contents:\n" + cat "${f}" ((WARN++)) if [[ $STATUS != 2 ]]; then STATUS=1 @@ -151,25 +158,25 @@ function checkRoot { if [ -d ${uhome}/ ]; then if [ -d ${uhome}/.ssh/ ]; then if ls ${uhome}/.ssh/*> /dev/null 2>&1; then - for key in ${uhome}/.ssh/* + for key in "${uhome}"/.ssh/* do if [ "${key}" == "${uhome}/.ssh/authorized_keys" ]; then - if [ "$( cat "${key}" | wc -c)" -gt 50 ]; then + if [ "$(wc -c < "${key}")" -gt 50 ]; then echo -en "\e[41m[FAIL]\e[0m User \e[1m${user}\e[0m has a populated authorized_keys file in \e[93m${key}\e[0m\n" - akey=$(cat ${key}) + akey=$(cat "${key}") echo "File Contents:" - echo $akey + echo "$akey" echo "--------------" ((FAIL++)) STATUS=2 fi elif [ "${key}" == "${uhome}/.ssh/id_rsa" ]; then - if [ "$( cat "${key}" | wc -c)" -gt 0 ]; then + if [ "$(wc -c < "${key}")" -gt 0 ]; then echo -en "\e[41m[FAIL]\e[0m User \e[1m${user}\e[0m has a private key file in \e[93m${key}\e[0m\n" - akey=$(cat ${key}) + akey=$(cat "${key}") echo "File Contents:" - echo $akey + echo "$akey" echo "--------------" ((FAIL++)) STATUS=2 @@ -187,7 +194,7 @@ function checkRoot { STATUS=1 fi else - if [ "$( cat "${key}" | wc -c)" -gt 50 ]; then + if [ "$(wc -c < "${key}")" -gt 50 ]; then echo -en "\e[93m[WARN]\e[0m User \e[1m${user}\e[0m has a populated known_hosts file in \e[93m${key}\e[0m\n" ((WARN++)) if [[ $STATUS != 2 ]]; then @@ -204,7 +211,7 @@ function checkRoot { fi if [ -f /root/.bash_history ];then - BH_S=$( cat /root/.bash_history | wc -c) + BH_S=$(wc -c < /root/.bash_history) if [[ $BH_S -lt 200 ]]; then echo -en "\e[32m[PASS]\e[0m ${user}'s Bash History appears to have been cleared\n" @@ -229,7 +236,7 @@ function checkRoot { function checkUsers { # Check each user-created account - for user in $(awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' /etc/passwd;) + awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' < /etc/passwd | while IFS= read -r user; do # Skip some other non-user system accounts if [[ $user == "centos" ]]; then @@ -244,9 +251,11 @@ function checkUsers { if [[ "${u[0]}" == "${user}" ]]; then if [[ ${u[1]} == "!" ]] || [[ ${u[1]} == "!!" ]] || [[ ${u[1]} == "*" ]]; then echo -en "\e[32m[PASS]\e[0m User ${user} has no password set.\n" + # shellcheck disable=SC2030 ((PASS++)) else echo -en "\e[41m[FAIL]\e[0m User ${user} has a password set on their account. Only system users are allowed on the image.\n" + # shellcheck disable=SC2030 ((FAIL++)) STATUS=2 fi @@ -257,29 +266,30 @@ function checkUsers { if [ -d "${uhome}/" ]; then if [ -d "${uhome}/.ssh/" ]; then if ls "${uhome}/.ssh/*"> /dev/null 2>&1; then - for key in ${uhome}/.ssh/* + for key in "${uhome}"/.ssh/* do if [ "${key}" == "${uhome}/.ssh/authorized_keys" ]; then - if [ "$( cat "${key}" | wc -c)" -gt 50 ]; then + if [ "$(wc -c < "${key}")" -gt 50 ]; then echo -en "\e[41m[FAIL]\e[0m User \e[1m${user}\e[0m has a populated authorized_keys file in \e[93m${key}\e[0m\n" - akey=$(cat ${key}) + akey=$(cat "${key}") echo "File Contents:" - echo $akey + echo "$akey" echo "--------------" ((FAIL++)) STATUS=2 fi elif [ "${key}" == "${uhome}/.ssh/id_rsa" ]; then - if [ "$( cat "${key}" | wc -c)" -gt 0 ]; then + if [ "$(wc -c < "${key}")" -gt 0 ]; then echo -en "\e[41m[FAIL]\e[0m User \e[1m${user}\e[0m has a private key file in \e[93m${key}\e[0m\n" - akey=$(cat ${key}) + akey=$(cat "${key}") echo "File Contents:" - echo $akey + echo "$akey" echo "--------------" ((FAIL++)) STATUS=2 else echo -en "\e[93m[WARN]\e[0m User \e[1m${user}\e[0m has empty private key file in \e[93m${key}\e[0m\n" + # shellcheck disable=SC2030 ((WARN++)) if [[ $STATUS != 2 ]]; then STATUS=1 @@ -294,7 +304,7 @@ function checkUsers { fi else - if [ "$( cat "${key}" | wc -c)" -gt 50 ]; then + if [ "$(wc -c < "${key}")" -gt 50 ]; then echo -en "\e[93m[WARN]\e[0m User \e[1m${user}\e[0m has a known_hosts file in \e[93m${key}\e[0m\n" ((WARN++)) if [[ $STATUS != 2 ]]; then @@ -317,7 +327,7 @@ function checkUsers { # Check for an uncleared .bash_history for this user if [ -f "${uhome}/.bash_history" ]; then - BH_S=$( cat "${uhome}/.bash_history" | wc -c ) + BH_S=$(wc -c < "${uhome}/.bash_history") if [[ $BH_S -lt 200 ]]; then echo -en "\e[32m[PASS]\e[0m ${user}'s Bash History appears to have been cleared\n" @@ -340,9 +350,11 @@ function checkFirewall { ufwa=$(ufw status |head -1| sed -e "s/^Status:\ //") if [[ $ufwa == "active" ]]; then FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n" + # shellcheck disable=SC2031 ((PASS++)) else FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n" + # shellcheck disable=SC2031 ((WARN++)) fi elif [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]] || [[ $OS == "AlmaLinux" ]]; then @@ -399,7 +411,7 @@ function checkFirewall { else # user could be using vanilla iptables, check if kernel module is loaded fw="iptables" - if [[ $(lsmod | grep -q '^ip_tables' 2>/dev/null) ]]; then + if lsmod | grep -q '^ip_tables' 2>/dev/null; then FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n" ((PASS++)) else @@ -412,7 +424,7 @@ function checkFirewall { } function checkUpdates { if [[ $OS == "Ubuntu" ]] || [[ "$OS" =~ Debian.* ]]; then - # ensure /tmp exists and has the proper permissions before + # Ensure /tmp exists and has the proper permissions before # checking for security updates # https://github.com/digitalocean/marketplace-partners/issues/94 if [[ ! -d /tmp ]]; then @@ -423,9 +435,9 @@ function checkUpdates { echo -en "\nUpdating apt package database to check for security updates, this may take a minute...\n\n" apt-get -y update > /dev/null - uc=$(apt-get --just-print upgrade | grep -i "security" | wc -l) + uc=$(apt-get --just-print upgrade | grep -i "security" -c) if [[ $uc -gt 0 ]]; then - update_count=$(( ${uc} / 2 )) + update_count=$(( uc / 2 )) else update_count=0 fi @@ -437,12 +449,14 @@ function checkUpdates { sleep 2 apt-get --just-print upgrade | grep -i security | awk '{print $2}' | awk '!seen[$0]++' echo -en + # shellcheck disable=SC2031 ((FAIL++)) STATUS=2 else echo -en "\e[32m[PASS]\e[0m There are no pending security updates for this image.\n\n" + ((PASS++)) fi - elif [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]]; then + elif [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]] || [[ $OS == "AlmaLinux" ]]; then echo -en "\nChecking for available security updates, this may take a minute...\n\n" update_count=$(yum check-update --security --quiet | wc -l) @@ -454,18 +468,6 @@ function checkUpdates { echo -en "\e[32m[PASS]\e[0m There are no pending security updates for this image.\n" ((PASS++)) fi - elif [[ $OS == "AlmaLinux" ]]; then - echo -en "\nChecking for available security updates, this may take a minute...\n\n" - - update_count=$(yum updateinfo list --quiet | wc -l) # https://errata.almalinux.org/ - if [[ $update_count -gt 0 ]]; then - echo -en "\e[41m[FAIL]\e[0m There are ${update_count} security updates available for this image that have not been installed.\n" - ((FAIL++)) - STATUS=2 - else - echo -en "\e[32m[PASS]\e[0m There are no pending security updates for this image.\n" - ((PASS++)) - fi else echo "Error encountered" exit 1 @@ -485,81 +487,6 @@ function checkCloudInit { fi return 1 } -function checkMongoDB { - # Check if MongoDB is installed - # If it is, verify the version is allowed (non-SSPL) - - if [[ $OS == "Ubuntu" ]] || [[ "$OS" =~ Debian.* ]]; then - - if [[ -f "/usr/bin/mongod" ]]; then - version=$(/usr/bin/mongod --version --quiet | grep "db version" | sed -e "s/^db\ version\ v//") - - if version_gt $version 4.0.0; then - if version_gt $version 4.0.3; then - echo -en "\e[41m[FAIL]\e[0m An SSPL version of MongoDB is present, ${version}" - ((FAIL++)) - STATUS=2 - else - echo -en "\e[32m[PASS]\e[0m The version of MongoDB installed, ${version} is not under the SSPL" - ((PASS++)) - fi - else - if version_gt $version 3.6.8; then - echo -en "\e[41m[FAIL]\e[0m An SSPL version of MongoDB is present, ${version}" - ((FAIL++)) - STATUS=2 - else - echo -en "\e[32m[PASS]\e[0m The version of MongoDB installed, ${version} is not under the SSPL" - ((PASS++)) - fi - fi - - - else - echo -en "\e[32m[PASS]\e[0m MongoDB is not installed" - ((PASS++)) - fi - - elif [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]] || [[ $OS == "AlmaLinux" ]]; then - - if [[ -f "/usr/bin/mongod" ]]; then - version=$(/usr/bin/mongod --version --quiet | grep "db version" | sed -e "s/^db\ version\ v//") - if version_gt $version 4.0.0; then - if version_gt $version 4.0.3; then - echo -en "\e[41m[FAIL]\e[0m An SSPL version of MongoDB is present" - ((FAIL++)) - STATUS=2 - else - echo -en "\e[32m[PASS]\e[0m The version of MongoDB installed is not under the SSPL" - ((PASS++)) - fi - else - if version_gt $version 3.6.8; then - echo -en "\e[41m[FAIL]\e[0m An SSPL version of MongoDB is present" - ((FAIL++)) - STATUS=2 - else - echo -en "\e[32m[PASS]\e[0m The version of MongoDB installed is not under the SSPL" - ((PASS++)) - fi - fi - - - - else - echo -en "\e[32m[PASS]\e[0m MongoDB is not installed" - ((PASS++)) - fi - - else - echo "ERROR: Unable to identify distribution" - ((FAIL++)) - STATUS 2 - return 1 - fi - - -} function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; } @@ -579,16 +506,8 @@ osv=0 if [[ $OS == "Ubuntu" ]]; then ost=1 - if [[ $VER == "22.04" ]]; then + if [[ $VER == "22.10" ]] || [[ $VER == "22.04" ]] || [[ $VER == "20.04" ]] || [[ $VER == "18.04" ]] || [[ $VER == "16.04" ]]; then osv=1 - elif [[ $VER == "20.04" ]]; then - osv=1 - elif [[ $VER == "18.04" ]]; then - osv=1 - elif [[ $VER == "16.04" ]]; then - osv=1 - else - osv=0 fi elif [[ "$OS" =~ Debian.* ]]; then @@ -600,6 +519,9 @@ elif [[ "$OS" =~ Debian.* ]]; then 10) osv=1 ;; + 11) + osv=1 + ;; *) osv=2 ;; @@ -625,14 +547,14 @@ elif [[ $OS == "CentOS Stream" ]]; then fi elif [[ $OS == "Rocky Linux" ]]; then ost=1 - if [[ $VER =~ "8." ]]; then + if [[ $VER =~ 8\. ]]; then osv=1 else osv=2 fi elif [[ $OS == "AlmaLinux" ]]; then ost=1 - if [[ $VER =~ "8." ]]; then + if [[ "$VERSION" =~ 8.* ]] || [[ "$VERSION" =~ 9.* ]]; then osv=1 else osv=2 @@ -684,8 +606,6 @@ checkRoot checkAgent -checkMongoDB - # Summary echo -en "\n\n---------------------------------------------------------------------------------------------------\n" @@ -712,4 +632,4 @@ elif [[ $STATUS == 1 ]]; then else echo -en "Some critical tests failed. These items must be resolved and this scan re-run before you submit your image to the DigitalOcean Marketplace.\n\n" exit 1 -fi +fi \ No newline at end of file diff --git a/setup/docker/cloud/digitalocean/cleanup.sh b/setup/docker/cloud/digitalocean/cleanup.sh index a51421564..7ebc0e9ed 100755 --- a/setup/docker/cloud/digitalocean/cleanup.sh +++ b/setup/docker/cloud/digitalocean/cleanup.sh @@ -35,7 +35,7 @@ rm -rf /var/lib/cloud/instances/* rm -f /root/.ssh/authorized_keys /etc/ssh/*key* touch /etc/ssh/revoked_keys chmod 600 /etc/ssh/revoked_keys -rm -f /var/log/kern.log /var/log/ufw.log +rm -f /var/log/*.log # Securely erase the unused portion of the filesystem GREEN='\033[0;32m' @@ -47,4 +47,4 @@ The secure erase will complete successfully when you see:${NC} dd: writing to '/zerofile': No space left on device\n Beginning secure erase now\n" -dd if=/dev/zero of=/zerofile bs=4096 || rm /zerofile +dd if=/dev/zero of=/zerofile bs=4096 || rm /zerofile \ No newline at end of file