You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

627 lines
22 KiB

  1. #!/bin/bash
  2. # DigitalOcean Marketplace Image Validation Tool
  3. # © 2021-2022 DigitalOcean LLC.
  4. # This code is licensed under Apache 2.0 license (see LICENSE.md for details)
  5. VERSION="v. 1.8"
  6. RUNDATE=$( date )
  7. # Script should be run with SUDO
  8. if [ "$EUID" -ne 0 ]
  9. then echo "[Error] - This script must be run with sudo or as the root user."
  10. exit 1
  11. fi
  12. STATUS=0
  13. PASS=0
  14. WARN=0
  15. FAIL=0
  16. # $1 == command to check for
  17. # returns: 0 == true, 1 == false
  18. cmdExists() {
  19. if command -v "$1" > /dev/null 2>&1; then
  20. return 0
  21. else
  22. return 1
  23. fi
  24. }
  25. function getDistro {
  26. if [ -f /etc/os-release ]; then
  27. # freedesktop.org and systemd
  28. # shellcheck disable=SC1091
  29. . /etc/os-release
  30. OS=$NAME
  31. VER=$VERSION_ID
  32. elif type lsb_release >/dev/null 2>&1; then
  33. # linuxbase.org
  34. OS=$(lsb_release -si)
  35. VER=$(lsb_release -sr)
  36. elif [ -f /etc/lsb-release ]; then
  37. # For some versions of Debian/Ubuntu without lsb_release command
  38. # shellcheck disable=SC1091
  39. . /etc/lsb-release
  40. OS=$DISTRIB_ID
  41. VER=$DISTRIB_RELEASE
  42. elif [ -f /etc/debian_version ]; then
  43. # Older Debian/Ubuntu/etc.
  44. OS=Debian
  45. VER=$(cat /etc/debian_version)
  46. elif [ -f /etc/SuSe-release ]; then
  47. # Older SuSE/etc.
  48. :
  49. elif [ -f /etc/redhat-release ]; then
  50. # Older Red Hat, CentOS, etc.
  51. VER=$(cut -d" " -f3 < /etc/redhat-release | cut -d "." -f1)
  52. d=$(cut -d" " -f1 < /etc/redhat-release | cut -d "." -f1)
  53. if [[ $d == "CentOS" ]]; then
  54. OS="CentOS Linux"
  55. fi
  56. else
  57. # Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
  58. OS=$(uname -s)
  59. VER=$(uname -r)
  60. fi
  61. }
  62. function loadPasswords {
  63. SHADOW=$(cat /etc/shadow)
  64. }
  65. function checkAgent {
  66. # Check for the presence of the DO directory in the filesystem
  67. if [ -d /opt/digitalocean ];then
  68. echo -en "\e[41m[FAIL]\e[0m DigitalOcean directory detected.\n"
  69. ((FAIL++))
  70. STATUS=2
  71. if [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]]; then
  72. echo "To uninstall the agent: 'sudo yum remove droplet-agent'"
  73. echo "To remove the DO directory: 'find /opt/digitalocean/ -type d -empty -delete'"
  74. elif [[ $OS == "Ubuntu" ]] || [[ $OS == "Debian" ]]; then
  75. echo "To uninstall the agent and remove the DO directory: 'sudo apt-get purge droplet-agent'"
  76. fi
  77. else
  78. echo -en "\e[32m[PASS]\e[0m DigitalOcean Monitoring agent was not found\n"
  79. ((PASS++))
  80. fi
  81. }
  82. function checkLogs {
  83. cp_ignore="/var/log/cpanel-install.log"
  84. echo -en "\nChecking for log files in /var/log\n\n"
  85. # Check if there are log archives or log files that have not been recently cleared.
  86. for f in /var/log/*-????????; do
  87. [[ -e $f ]] || break
  88. if [ "${f}" != "${cp_ignore}" ]; then
  89. echo -en "\e[93m[WARN]\e[0m Log archive ${f} found; Contents:\n"
  90. cat "${f}"
  91. ((WARN++))
  92. if [[ $STATUS != 2 ]]; then
  93. STATUS=1
  94. fi
  95. fi
  96. done
  97. for f in /var/log/*.[0-9];do
  98. [[ -e $f ]] || break
  99. echo -en "\e[93m[WARN]\e[0m Log archive ${f} found; Contents:\n"
  100. cat "${f}"
  101. ((WARN++))
  102. if [[ $STATUS != 2 ]]; then
  103. STATUS=1
  104. fi
  105. done
  106. for f in /var/log/*.log; do
  107. [[ -e $f ]] || break
  108. 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
  109. if [ "${f}" != "${cp_ignore}" ]; then
  110. echo -en "\e[93m[WARN]\e[0m un-cleared log file, ${f} found; Contents:\n"
  111. cat "${f}"
  112. ((WARN++))
  113. if [[ $STATUS != 2 ]]; then
  114. STATUS=1
  115. fi
  116. fi
  117. elif [[ "${f}" != '/var/log/lfd.log' && "$(wc -c < "${f}")" -gt 50 ]]; then
  118. if [ "${f}" != "${cp_ignore}" ]; then
  119. echo -en "\e[93m[WARN]\e[0m un-cleared log file, ${f} found; Contents:\n"
  120. cat "${f}"
  121. ((WARN++))
  122. if [[ $STATUS != 2 ]]; then
  123. STATUS=1
  124. fi
  125. fi
  126. fi
  127. done
  128. }
  129. function checkTMP {
  130. # Check the /tmp directory to ensure it is empty. Warn on any files found.
  131. return 1
  132. }
  133. function checkRoot {
  134. user="root"
  135. uhome="/root"
  136. for usr in $SHADOW
  137. do
  138. IFS=':' read -r -a u <<< "$usr"
  139. if [[ "${u[0]}" == "${user}" ]]; then
  140. if [[ ${u[1]} == "!" ]] || [[ ${u[1]} == "!!" ]] || [[ ${u[1]} == "*" ]]; then
  141. echo -en "\e[32m[PASS]\e[0m User ${user} has no password set.\n"
  142. ((PASS++))
  143. else
  144. echo -en "\e[41m[FAIL]\e[0m User ${user} has a password set on their account.\n"
  145. ((FAIL++))
  146. STATUS=2
  147. fi
  148. fi
  149. done
  150. if [ -d ${uhome}/ ]; then
  151. if [ -d ${uhome}/.ssh/ ]; then
  152. if ls ${uhome}/.ssh/*> /dev/null 2>&1; then
  153. for key in "${uhome}"/.ssh/*
  154. do
  155. if [ "${key}" == "${uhome}/.ssh/authorized_keys" ]; then
  156. if [ "$(wc -c < "${key}")" -gt 50 ]; then
  157. 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"
  158. akey=$(cat "${key}")
  159. echo "File Contents:"
  160. echo "$akey"
  161. echo "--------------"
  162. ((FAIL++))
  163. STATUS=2
  164. fi
  165. elif [ "${key}" == "${uhome}/.ssh/id_rsa" ]; then
  166. if [ "$(wc -c < "${key}")" -gt 0 ]; then
  167. 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"
  168. akey=$(cat "${key}")
  169. echo "File Contents:"
  170. echo "$akey"
  171. echo "--------------"
  172. ((FAIL++))
  173. STATUS=2
  174. else
  175. 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"
  176. ((WARN++))
  177. if [[ $STATUS != 2 ]]; then
  178. STATUS=1
  179. fi
  180. fi
  181. elif [ "${key}" != "${uhome}/.ssh/known_hosts" ]; then
  182. echo -en "\e[93m[WARN]\e[0m User \e[1m${user}\e[0m has a file in their .ssh directory at \e[93m${key}\e[0m\n"
  183. ((WARN++))
  184. if [[ $STATUS != 2 ]]; then
  185. STATUS=1
  186. fi
  187. else
  188. if [ "$(wc -c < "${key}")" -gt 50 ]; then
  189. 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"
  190. ((WARN++))
  191. if [[ $STATUS != 2 ]]; then
  192. STATUS=1
  193. fi
  194. fi
  195. fi
  196. done
  197. else
  198. echo -en "\e[32m[ OK ]\e[0m User \e[1m${user}\e[0m has no SSH keys present\n"
  199. fi
  200. else
  201. echo -en "\e[32m[ OK ]\e[0m User \e[1m${user}\e[0m does not have an .ssh directory\n"
  202. fi
  203. if [ -f /root/.bash_history ];then
  204. BH_S=$(wc -c < /root/.bash_history)
  205. if [[ $BH_S -lt 200 ]]; then
  206. echo -en "\e[32m[PASS]\e[0m ${user}'s Bash History appears to have been cleared\n"
  207. ((PASS++))
  208. else
  209. echo -en "\e[41m[FAIL]\e[0m ${user}'s Bash History should be cleared to prevent sensitive information from leaking\n"
  210. ((FAIL++))
  211. STATUS=2
  212. fi
  213. return 1;
  214. else
  215. echo -en "\e[32m[PASS]\e[0m The Root User's Bash History is not present\n"
  216. ((PASS++))
  217. fi
  218. else
  219. echo -en "\e[32m[ OK ]\e[0m User \e[1m${user}\e[0m does not have a directory in /home\n"
  220. fi
  221. echo -en "\n\n"
  222. return 1
  223. }
  224. function checkUsers {
  225. # Check each user-created account
  226. awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' < /etc/passwd | while IFS= read -r user;
  227. do
  228. # Skip some other non-user system accounts
  229. if [[ $user == "centos" ]]; then
  230. :
  231. elif [[ $user == "nfsnobody" ]]; then
  232. :
  233. else
  234. echo -en "\nChecking user: ${user}...\n"
  235. for usr in $SHADOW
  236. do
  237. IFS=':' read -r -a u <<< "$usr"
  238. if [[ "${u[0]}" == "${user}" ]]; then
  239. if [[ ${u[1]} == "!" ]] || [[ ${u[1]} == "!!" ]] || [[ ${u[1]} == "*" ]]; then
  240. echo -en "\e[32m[PASS]\e[0m User ${user} has no password set.\n"
  241. # shellcheck disable=SC2030
  242. ((PASS++))
  243. else
  244. 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"
  245. # shellcheck disable=SC2030
  246. ((FAIL++))
  247. STATUS=2
  248. fi
  249. fi
  250. done
  251. #echo "User Found: ${user}"
  252. uhome="/home/${user}"
  253. if [ -d "${uhome}/" ]; then
  254. if [ -d "${uhome}/.ssh/" ]; then
  255. if ls "${uhome}/.ssh/*"> /dev/null 2>&1; then
  256. for key in "${uhome}"/.ssh/*
  257. do
  258. if [ "${key}" == "${uhome}/.ssh/authorized_keys" ]; then
  259. if [ "$(wc -c < "${key}")" -gt 50 ]; then
  260. 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"
  261. akey=$(cat "${key}")
  262. echo "File Contents:"
  263. echo "$akey"
  264. echo "--------------"
  265. ((FAIL++))
  266. STATUS=2
  267. fi
  268. elif [ "${key}" == "${uhome}/.ssh/id_rsa" ]; then
  269. if [ "$(wc -c < "${key}")" -gt 0 ]; then
  270. 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"
  271. akey=$(cat "${key}")
  272. echo "File Contents:"
  273. echo "$akey"
  274. echo "--------------"
  275. ((FAIL++))
  276. STATUS=2
  277. else
  278. 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"
  279. # shellcheck disable=SC2030
  280. ((WARN++))
  281. if [[ $STATUS != 2 ]]; then
  282. STATUS=1
  283. fi
  284. fi
  285. elif [ "${key}" != "${uhome}/.ssh/known_hosts" ]; then
  286. echo -en "\e[93m[WARN]\e[0m User \e[1m${user}\e[0m has a file in their .ssh directory named \e[93m${key}\e[0m\n"
  287. ((WARN++))
  288. if [[ $STATUS != 2 ]]; then
  289. STATUS=1
  290. fi
  291. else
  292. if [ "$(wc -c < "${key}")" -gt 50 ]; then
  293. 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"
  294. ((WARN++))
  295. if [[ $STATUS != 2 ]]; then
  296. STATUS=1
  297. fi
  298. fi
  299. fi
  300. done
  301. else
  302. echo -en "\e[32m[ OK ]\e[0m User \e[1m${user}\e[0m has no SSH keys present\n"
  303. fi
  304. else
  305. echo -en "\e[32m[ OK ]\e[0m User \e[1m${user}\e[0m does not have an .ssh directory\n"
  306. fi
  307. else
  308. echo -en "\e[32m[ OK ]\e[0m User \e[1m${user}\e[0m does not have a directory in /home\n"
  309. fi
  310. # Check for an uncleared .bash_history for this user
  311. if [ -f "${uhome}/.bash_history" ]; then
  312. BH_S=$(wc -c < "${uhome}/.bash_history")
  313. if [[ $BH_S -lt 200 ]]; then
  314. echo -en "\e[32m[PASS]\e[0m ${user}'s Bash History appears to have been cleared\n"
  315. ((PASS++))
  316. else
  317. echo -en "\e[41m[FAIL]\e[0m ${user}'s Bash History should be cleared to prevent sensitive information from leaking\n"
  318. ((FAIL++))
  319. STATUS=2
  320. fi
  321. echo -en "\n\n"
  322. fi
  323. fi
  324. done
  325. }
  326. function checkFirewall {
  327. if [[ $OS == "Ubuntu" ]]; then
  328. fw="ufw"
  329. ufwa=$(ufw status |head -1| sed -e "s/^Status:\ //")
  330. if [[ $ufwa == "active" ]]; then
  331. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  332. # shellcheck disable=SC2031
  333. ((PASS++))
  334. else
  335. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  336. # shellcheck disable=SC2031
  337. ((WARN++))
  338. fi
  339. elif [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]]; then
  340. if [ -f /usr/lib/systemd/system/csf.service ]; then
  341. fw="csf"
  342. if [[ $(systemctl status $fw >/dev/null 2>&1) ]]; then
  343. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  344. ((PASS++))
  345. elif cmdExists "firewall-cmd"; then
  346. if [[ $(systemctl is-active firewalld >/dev/null 2>&1 && echo 1 || echo 0) ]]; then
  347. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  348. ((PASS++))
  349. else
  350. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  351. ((WARN++))
  352. fi
  353. else
  354. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  355. ((WARN++))
  356. fi
  357. else
  358. fw="firewalld"
  359. if [[ $(systemctl is-active firewalld >/dev/null 2>&1 && echo 1 || echo 0) ]]; then
  360. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  361. ((PASS++))
  362. else
  363. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  364. ((WARN++))
  365. fi
  366. fi
  367. elif [[ "$OS" =~ Debian.* ]]; then
  368. # user could be using a number of different services for managing their firewall
  369. # we will check some of the most common
  370. if cmdExists 'ufw'; then
  371. fw="ufw"
  372. ufwa=$(ufw status |head -1| sed -e "s/^Status:\ //")
  373. if [[ $ufwa == "active" ]]; then
  374. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  375. ((PASS++))
  376. else
  377. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  378. ((WARN++))
  379. fi
  380. elif cmdExists "firewall-cmd"; then
  381. fw="firewalld"
  382. if [[ $(systemctl is-active --quiet $fw) ]]; then
  383. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  384. ((PASS++))
  385. else
  386. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  387. ((WARN++))
  388. fi
  389. else
  390. # user could be using vanilla iptables, check if kernel module is loaded
  391. fw="iptables"
  392. if lsmod | grep -q '^ip_tables' 2>/dev/null; then
  393. FW_VER="\e[32m[PASS]\e[0m Firewall service (${fw}) is active\n"
  394. ((PASS++))
  395. else
  396. FW_VER="\e[93m[WARN]\e[0m No firewall is configured. Ensure ${fw} is installed and configured\n"
  397. ((WARN++))
  398. fi
  399. fi
  400. fi
  401. }
  402. function checkUpdates {
  403. if [[ $OS == "Ubuntu" ]] || [[ "$OS" =~ Debian.* ]]; then
  404. # Ensure /tmp exists and has the proper permissions before
  405. # checking for security updates
  406. # https://github.com/digitalocean/marketplace-partners/issues/94
  407. if [[ ! -d /tmp ]]; then
  408. mkdir /tmp
  409. fi
  410. chmod 1777 /tmp
  411. echo -en "\nUpdating apt package database to check for security updates, this may take a minute...\n\n"
  412. apt-get -y update > /dev/null
  413. uc=$(apt-get --just-print upgrade | grep -i "security" -c)
  414. if [[ $uc -gt 0 ]]; then
  415. update_count=$(( uc / 2 ))
  416. else
  417. update_count=0
  418. fi
  419. if [[ $update_count -gt 0 ]]; then
  420. echo -en "\e[41m[FAIL]\e[0m There are ${update_count} security updates available for this image that have not been installed.\n"
  421. echo -en
  422. echo -en "Here is a list of the security updates that are not installed:\n"
  423. sleep 2
  424. apt-get --just-print upgrade | grep -i security | awk '{print $2}' | awk '!seen[$0]++'
  425. echo -en
  426. # shellcheck disable=SC2031
  427. ((FAIL++))
  428. STATUS=2
  429. else
  430. echo -en "\e[32m[PASS]\e[0m There are no pending security updates for this image.\n\n"
  431. ((PASS++))
  432. fi
  433. elif [[ $OS == "CentOS Linux" ]] || [[ $OS == "CentOS Stream" ]] || [[ $OS == "Rocky Linux" ]]; then
  434. echo -en "\nChecking for available security updates, this may take a minute...\n\n"
  435. update_count=$(yum check-update --security --quiet | wc -l)
  436. if [[ $update_count -gt 0 ]]; then
  437. echo -en "\e[41m[FAIL]\e[0m There are ${update_count} security updates available for this image that have not been installed.\n"
  438. ((FAIL++))
  439. STATUS=2
  440. else
  441. echo -en "\e[32m[PASS]\e[0m There are no pending security updates for this image.\n"
  442. ((PASS++))
  443. fi
  444. else
  445. echo "Error encountered"
  446. exit 1
  447. fi
  448. return 1;
  449. }
  450. function checkCloudInit {
  451. if hash cloud-init 2>/dev/null; then
  452. CI="\e[32m[PASS]\e[0m Cloud-init is installed.\n"
  453. ((PASS++))
  454. else
  455. CI="\e[41m[FAIL]\e[0m No valid verison of cloud-init was found.\n"
  456. ((FAIL++))
  457. STATUS=2
  458. fi
  459. return 1
  460. }
  461. function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
  462. clear
  463. echo "DigitalOcean Marketplace Image Validation Tool ${VERSION}"
  464. echo "Executed on: ${RUNDATE}"
  465. echo "Checking local system for Marketplace compatibility..."
  466. getDistro
  467. echo -en "\n\e[1mDistribution:\e[0m ${OS}\n"
  468. echo -en "\e[1mVersion:\e[0m ${VER}\n\n"
  469. ost=0
  470. osv=0
  471. if [[ $OS == "Ubuntu" ]]; then
  472. ost=1
  473. if [[ $VER == "22.04" ]] || [[ $VER == "20.04" ]] || [[ $VER == "18.04" ]] || [[ $VER == "16.04" ]]; then
  474. osv=1
  475. fi
  476. elif [[ "$OS" =~ Debian.* ]]; then
  477. ost=1
  478. case "$VER" in
  479. 9)
  480. osv=1
  481. ;;
  482. 10)
  483. osv=1
  484. ;;
  485. 11)
  486. osv=1
  487. ;;
  488. *)
  489. osv=2
  490. ;;
  491. esac
  492. elif [[ $OS == "CentOS Linux" ]]; then
  493. ost=1
  494. if [[ $VER == "8" ]]; then
  495. osv=1
  496. elif [[ $VER == "7" ]]; then
  497. osv=1
  498. elif [[ $VER == "6" ]]; then
  499. osv=1
  500. else
  501. osv=2
  502. fi
  503. elif [[ $OS == "CentOS Stream" ]]; then
  504. ost=1
  505. if [[ $VER == "8" ]]; then
  506. osv=1
  507. else
  508. osv=2
  509. fi
  510. elif [[ $OS == "Rocky Linux" ]]; then
  511. ost=1
  512. if [[ $VER =~ 8\. ]]; then
  513. osv=1
  514. else
  515. osv=2
  516. fi
  517. else
  518. ost=0
  519. fi
  520. if [[ $ost == 1 ]]; then
  521. echo -en "\e[32m[PASS]\e[0m Supported Operating System Detected: ${OS}\n"
  522. ((PASS++))
  523. else
  524. echo -en "\e[41m[FAIL]\e[0m ${OS} is not a supported Operating System\n"
  525. ((FAIL++))
  526. STATUS=2
  527. fi
  528. if [[ $osv == 1 ]]; then
  529. echo -en "\e[32m[PASS]\e[0m Supported Release Detected: ${VER}\n"
  530. ((PASS++))
  531. elif [[ $ost == 1 ]]; then
  532. echo -en "\e[41m[FAIL]\e[0m ${OS} ${VER} is not a supported Operating System Version\n"
  533. ((FAIL++))
  534. STATUS=2
  535. else
  536. echo "Exiting..."
  537. exit 1
  538. fi
  539. checkCloudInit
  540. echo -en "${CI}"
  541. checkFirewall
  542. echo -en "${FW_VER}"
  543. checkUpdates
  544. loadPasswords
  545. checkLogs
  546. echo -en "\n\nChecking all user-created accounts...\n"
  547. checkUsers
  548. echo -en "\n\nChecking the root account...\n"
  549. checkRoot
  550. checkAgent
  551. # Summary
  552. echo -en "\n\n---------------------------------------------------------------------------------------------------\n"
  553. if [[ $STATUS == 0 ]]; then
  554. echo -en "Scan Complete.\n\e[32mAll Tests Passed!\e[0m\n"
  555. elif [[ $STATUS == 1 ]]; then
  556. echo -en "Scan Complete. \n\e[93mSome non-critical tests failed. Please review these items.\e[0m\e[0m\n"
  557. else
  558. echo -en "Scan Complete. \n\e[41mOne or more tests failed. Please review these items and re-test.\e[0m\n"
  559. fi
  560. echo "---------------------------------------------------------------------------------------------------"
  561. echo -en "\e[1m${PASS} Tests PASSED\e[0m\n"
  562. echo -en "\e[1m${WARN} WARNINGS\e[0m\n"
  563. echo -en "\e[1m${FAIL} Tests FAILED\e[0m\n"
  564. echo -en "---------------------------------------------------------------------------------------------------\n"
  565. if [[ $STATUS == 0 ]]; then
  566. echo -en "We did not detect any issues with this image. Please be sure to manually ensure that all software installed on the base system is functional, secure and properly configured (or facilities for configuration on first-boot have been created).\n\n"
  567. exit 0
  568. elif [[ $STATUS == 1 ]]; then
  569. echo -en "Please review all [WARN] items above and ensure they are intended or resolved. If you do not have a specific requirement, we recommend resolving these items before image submission\n\n"
  570. exit 0
  571. else
  572. 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"
  573. exit 1
  574. fi