Quick Install Script for Vulnerability Management (InsightVM) in InsightGovCloud
Copy and paste this code block into a new file and follow the Linux installation instructions in Deploy Vulnerability Management (InsightVM) in InsightGovCloud.
ℹ️
Tip for copying code blocks
Hover your cursor over a code block to make the Copy code button appear. Click this button to copy the entire code block to your clipboard.
Folder highlights
Script content details the unattended Linux installation for Vulnerability Management (InsightVM) InsightGovCloud, including password policy checks and FIPS mode configuration steps.
# !/bin/bash
set -euo pipefail
#
# FedRamp Linux Quick Start Script (v0.98)
# - Security: downloads SHA-512 checksum and verifies installer before execution.
# - Collects required user inputs and enforces a basic password policy (min 8 chars, mixed case, digit, special)
# - Ease of use: uses unattended install with direct cli call (not response.vars)
# - Performance: polling loop for log markers
# - Compatibility: avoids "bash -lc" login shell behavior; uses "bash -c".
# - Checks for Federal or FIPS = false
#
# - Verbose + colorized checks for existing install and FedRAMP/FIPS log markers
# - Existing install guard verifies: RNG (advisory), process running, log markers, CustomEnvironment.properties; exits success if compliant, fails otherwise
# - Uses /tmp for downloads (installer + checksum)
# --- Colors ---
C_RESET="\033[0m"
C_BOLD="\033[1m"
C_BLUE="\033[1;34m"
C_GRAY="\033[90m"
C_GREEN="\033[32m"
C_YELLOW="\033[33m"
C_RED="\033[31m"
ok() { echo -e "${C_GREEN}[SUCCESS]${C_RESET} $*"; }
warn() { echo -e "${C_YELLOW}[WARNING]${C_RESET} $*"; }
fail() { echo -e "${C_RED}[ERROR]${C_RESET} $*"; }
info() { echo -e "${C_BLUE}[INFO]${C_RESET} $*"; }
print_step() {
echo -e "\n${C_BLUE}${C_BOLD}==> $1${C_RESET}"
}
run_cmd() {
echo -e "${C_GRAY}$ $*${C_RESET}"
bash -c "$@"
}
have() { command -v "$1" >/dev/null 2>&1; }
# --- Password complexity ---
pw_error() { echo -e "${C_RED}Password policy error:${C_RESET} $1" >&2; }
check_password_complexity() {
local password="$1"
local username="${2:-}"
local min_len=8
info "Password policy: >=${min_len} chars, upper/lower/digit/special, no whitespace, no username substring"
if (( ${#password} < min_len )); then
pw_error "Password must be at least ${min_len} characters."
return 1
fi
if grep -qE '[[:space:]]' <<<"$password"; then
pw_error "Password must not contain whitespace."
return 1
fi
if ! grep -qE '[A-Z]' <<<"$password"; then
pw_error "Password must contain at least one uppercase letter."
return 1
fi
if ! grep -qE '[a-z]' <<<"$password"; then
pw_error "Password must contain at least one lowercase letter."
return 1
fi
if ! grep -qE '[0-9]' <<<"$password"; then
pw_error "Password must contain at least one digit."
return 1
fi
if ! grep -qE '[^A-Za-z0-9]' <<<"$password"; then
pw_error "Password must contain at least one special character."
return 1
fi
if [[ -n "$username" ]]; then
shopt -s nocasematch
if [[ "$password" == *"$username"* ]]; then
shopt -u nocasematch
pw_error "Password must not contain the username."
return 1
fi
shopt -u nocasematch
fi
ok "Password meets complexity requirements."
return 0
}
# --- RNG helpers ---
rng_service_candidates=("rngd" "rng-tools" "rng-tools-debian")
find_rng_service() {
for s in "${rng_service_candidates[@]}"; do
if systemctl list-unit-files --type=service 2>/dev/null | awk '{print $1}' | grep -qx "${s}.service"; then
echo "${s}.service"
return 0
fi
done
if have rngd; then
echo "rngd.service"
return 0
fi
return 1
}
# --- SELinux helpers ---
selinux_is_enabled() {
if have selinuxenabled; then
selinuxenabled && return 0 || return 1
fi
if have getenforce; then
[[ "$(getenforce 2>/dev/null || echo Disabled)" != "Disabled" ]] && return 0 || return 1
fi
return 1
}
# --- Process check (existing install) ---
# Must match cases like:
# root 4495 ... SCREEN -d -m -S nexposeconsole /opt/rapid7/nexpose/nsc/nsc.sh
nexpose_process_is_running() {
pgrep -fa "/opt/rapid7/nexpose/nsc/nsc\.sh" >/dev/null 2>&1
}
get_nexpose_process_line() {
# Return one representative line if present, formatted without the leading username
# e.g. "4495 SCREEN -d -m -S nexposeconsole /opt/rapid7/nexpose/nsc/nsc.sh"
pgrep -fa "/opt/rapid7/nexpose/nsc/nsc\.sh" 2>/dev/null | head -n 1 | awk '{ $1=$1; print }' || true
}
# --- Existing install detection (quiet) ---
nexpose_is_installed_quiet() {
[[ -d /opt/rapid7/nexpose/nsc ]] || return 1
[[ -f /opt/rapid7/nexpose/nsc/nsc.sh ]] || return 1
return 0
}
verify_existing_installation() {
print_step "Existing install detected. Verifying FedRAMP/FIPS compliance..."
ok "Existing install detected. Verifying FedRAMP/FIPS compliance..."
local LOG="/opt/rapid7/nexpose/nsc/logs/nsc.log"
local CUSTOM_ENV="/opt/rapid7/nexpose/nsc/CustomEnvironment.properties"
local MARK_FED_TRUE="Console is a Federal instance = true"
local MARK_FIPS_TRUE="Console FIPS Mode switched on = true"
local MARK_FED_FALSE="Console is a Federal instance = false"
local MARK_FIPS_FALSE="Console FIPS Mode switched on = false"
local log_ok=0
local env_ok=0
local rng_ok=0
local proc_ok=0
# Process (required) - print first on success
if nexpose_process_is_running; then
local pline
pline="$(get_nexpose_process_line)"
if [[ -n "$pline" ]]; then
ok "Process running: ${pline}"
else
ok "Process running: /opt/rapid7/nexpose/nsc/nsc.sh"
fi
proc_ok=1
fi
# RNG (advisory)
if RNG_SVC="$(find_rng_service 2>/dev/null)"; then
if systemctl is-active --quiet "$RNG_SVC"; then
ok "RNG active: $RNG_SVC"
rng_ok=1
else
warn "RNG installed but inactive: $RNG_SVC"
fi
else
warn "No RNG service detected."
fi
# Logs
if [[ -f "$LOG" ]]; then
if sudo grep -qF "$MARK_FED_FALSE" "$LOG" || sudo grep -qF "$MARK_FIPS_FALSE" "$LOG"; then
fail "Detected explicit non-compliant log markers (false)."
fail "Searched for false markers:"
fail " - $MARK_FED_FALSE"
fail " - $MARK_FIPS_FALSE"
echo -e "${C_GRAY}"
sudo grep -nE "Console is a Federal instance = |Console FIPS Mode switched on = " "$LOG" | tail -n 100 || true
echo -e "${C_RESET}"
# Continue to final failure summary below
else
if sudo grep -qF "$MARK_FED_TRUE" "$LOG" && sudo grep -qF "$MARK_FIPS_TRUE" "$LOG"; then
ok "Log markers verified (Federal=true, FIPS=true). Sample:"
log_ok=1
else
fail "FedRAMP/FIPS log verification failed."
fail "Search of logs did not find):"
if sudo grep -qF "$MARK_FED_TRUE" "$LOG"; then
fail " - ${MARK_FED_TRUE}. (Found)"
else
fail " - ${MARK_FED_TRUE}. (Not found)"
fi
if sudo grep -qF "$MARK_FIPS_TRUE" "$LOG"; then
fail " - ${MARK_FIPS_TRUE}. (Found)"
else
fail " - ${MARK_FIPS_TRUE}. (Not found)"
fi
fi
fi
else
fail "Log file not found."
fi
# CustomEnvironment.properties
if [[ -f "$CUSTOM_ENV" ]]; then
local miss=0
if ! grep -q "^com\.rapid7\.federal=true" "$CUSTOM_ENV"; then
fail "Missing/incorrect property: com.rapid7.federal=true"
miss=1
fi
if ! grep -q "^fipsMode=1" "$CUSTOM_ENV"; then
fail "Missing/incorrect property: fipsMode=1"
miss=1
fi
if (( miss == 0 )); then
env_ok=1
fi
else
fail "CustomEnvironment.properties not found."
fi
# Process requirement failure detail
if (( proc_ok != 1 )); then
fail "Process check failed: could not find running nsc.sh process."
info "Matching processes (if any):"
echo -e "${C_GRAY}"
ps -ef | grep -E "/opt/rapid7/nexpose/nsc/nsc\.sh|nexposeconsole|nsc\.sh" | grep -v grep || true
echo -e "${C_RESET}"
fi
if (( log_ok == 1 && env_ok == 1 && proc_ok == 1 )); then
ok "Existing installation is Federal + FIPS compliant. No changes made. Exiting."
if (( rng_ok != 1 )); then
warn "RNG not active; FIPS mode may not operate correctly."
fi
exit 0
fi
fail "Existing installation detected but not compliant. Aborting to avoid overwriting."
warn "Next Steps:"
warn " - Check that RNG is installed and running"
warn " - Ensure FIPS and Federal instance is configured in: ${CUSTOM_ENV}"
warn " - Make above checks, restart daemon, and re-run this script."
warn " - Logs: ${LOG}"
exit 1
}
# --- Existing installation guard (quiet; no pre-check output) ---
if nexpose_is_installed_quiet; then
verify_existing_installation
fi
# --- Collect user variables for unattended install ---
print_step "Collecting user variables for installer..."
read -rp "Enter company name: " NX_NAME
read -rp "Enter first name: " FIRST
read -rp "Enter last name: " LAST
read -rp "Enter console admin username: " NX_USERNAME
while true; do
read -rsp "Enter console admin password: " NX_PASSWORD
echo
read -rsp "Re-enter console admin password: " NX_PASSWORD2
echo
if [[ "$NX_PASSWORD" != "$NX_PASSWORD2" ]]; then
fail "Passwords do not match. Try again."
continue
fi
if ! check_password_complexity "$NX_PASSWORD" "$NX_USERNAME"; then
fail "Password does not meet complexity requirements. Try again."
continue
fi
ok "Password accepted."
break
done
# --- Package manager detection ---
PKG="unknown"
if have dnf; then
PKG="dnf"
elif have apt-get; then
PKG="apt"
elif have yum; then
PKG="dnf"
fi
if [[ "$PKG" == "unknown" ]]; then
fail "Unsupported distro. Need dnf or apt-get."
exit 1
fi
ok "Detected package manager: $PKG"
# --- Update and install prerequisites ---
print_step "Updating system packages..."
if [[ "$PKG" == "dnf" ]]; then
run_cmd "sudo dnf -y update"
elif [[ "$PKG" == "apt" ]]; then
run_cmd "sudo apt-get update -y"
fi
ok "System update complete."
print_step "Installing prerequisite packages (RNG, SELinux tools when available, curl)..."
if [[ "$PKG" == "dnf" ]]; then
run_cmd "sudo dnf -y install rng-tools policycoreutils policycoreutils-python-utils curl"
elif [[ "$PKG" == "apt" ]]; then
run_cmd "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y curl"
run_cmd "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y policycoreutils || true"
run_cmd "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y rng-tools5 || sudo DEBIAN_FRONTEND=noninteractive apt-get install -y rng-tools || true"
fi
ok "Prerequisites installed."
print_step "Enabling and starting RNG daemon..."
if RNG_SVC="$(find_rng_service 2>/dev/null)"; then
run_cmd "sudo systemctl enable --now ${RNG_SVC}"
if systemctl is-active --quiet "$RNG_SVC"; then
ok "RNG active: $RNG_SVC"
else
warn "RNG installed but not active yet: $RNG_SVC"
fi
else
warn "Could not detect rng daemon. FIPS mode may be impacted. Install will continue."
fi
# --- Directory setup ---
print_step "Creating /opt/rapid7/nexpose directory..."
run_cmd "sudo install -d -m 755 /opt/rapid7/nexpose"
run_cmd "sudo chown -R root:root /opt/rapid7"
ok "Directory prepared: /opt/rapid7/nexpose"
# --- SELinux pre-config (only if SELinux is enabled) ---
if selinux_is_enabled && have semanage; then
print_step "SELinux detected: labeling Rapid7 directories and opening TCP 3780..."
run_cmd "sudo semanage fcontext -a -t usr_t '/opt/rapid7(/.*)?' || true"
run_cmd "sudo semanage fcontext -a -t bin_t '/opt/rapid7/nexpose(/.*)?' || true"
run_cmd "sudo semanage fcontext -a -t var_log_t '/opt/rapid7/nexpose/nsc/logs(/.*)?' || true"
run_cmd "sudo semanage port -a -t http_port_t -p tcp 3780 2>/dev/null || sudo semanage port -m -t http_port_t -p tcp 3780 || true"
print_step "Applying SELinux labels..."
run_cmd "sudo restorecon -RF /opt/rapid7 || true"
ok "SELinux configuration applied (best-effort)."
else
warn "SELinux not enabled/detected or semanage missing. Skipping SELinux steps."
fi
# --- Download installer and verify checksum (in /tmp) ---
INSTALLER="/tmp/Rapid7Setup-Linux64.bin"
CHECKSUM_FILE="/tmp/Rapid7Setup-Linux64.bin.sha512sum"
print_step "Downloading Rapid7 Vulnerability Management (InsightVM) installer and checksum to /tmp..."
run_cmd "sudo curl -fL https://download2.rapid7.com/download/InsightVM/Rapid7Setup-Linux64.bin -o '${INSTALLER}'"
run_cmd "sudo curl -fL https://download2.rapid7.com/download/InsightVM/Rapid7Setup-Linux64.bin.sha512sum -o '${CHECKSUM_FILE}'"
ok "Downloads complete."
print_step "Verifying installer checksum..."
run_cmd "cd /tmp && sha512sum -c Rapid7Setup-Linux64.bin.sha512sum"
ok "Checksum verification successful."
run_cmd "sudo chmod +x '${INSTALLER}'"
ok "Installer marked executable."
# --- Run installer with -V args (no response.vars), avoid $Boolean expansion under set -u ---
print_step "Running Vulnerability Management (InsightVM) installer..."
warn "Password is supplied via command-line arguments; it may be visible to other processes via ps during install."
INSTALL_CMD=(
sudo "$INSTALLER" -q -overwrite
"-Vfirstname=$FIRST" "-Vlastname=$LAST"
"-Vcompany=$NX_NAME" "-Vusername=$NX_USERNAME"
"-Vpassword1=$NX_PASSWORD" "-Vpassword2=$NX_PASSWORD"
'-Vsys.component.typical$Boolean=true'
'-Vsys.component.engine$Boolean=false'
'-VcommunicationDirectionChoice$Integer=1'
'-VrequirePasswordChange$Boolean=true'
'-VinitService$Boolean=true'
)
echo -e "${C_GRAY}$ sudo $INSTALLER -q -overwrite -Vfirstname=... -Vlastname=... -Vcompany=... -Vusername=... -Vpassword1=REDACTED -Vpassword2=REDACTED ...${C_RESET}"
if "${INSTALL_CMD[@]}"; then
ok "Installer completed successfully."
else
fail "Installer returned a non-zero exit code."
exit 1
fi
# --- FIPS & FedRAMP configuration ---
print_step "Enabling InsightGovCloud and FIPS mode..."
run_cmd "sudo bash -c \"cat > /opt/rapid7/nexpose/nsc/CustomEnvironment.properties <<'EOF'
fipsMode=1
com.rapid7.federal=true
EOF
\""
ok "CustomEnvironment.properties written."
# Re-apply labels if SELinux is present
if selinux_is_enabled; then
print_step "Re-applying SELinux labels..."
run_cmd "sudo restorecon -RF /opt/rapid7/nexpose || true"
ok "SELinux labels re-applied."
else
warn "SELinux not enabled; skipping restorecon."
fi
# --- Start console service ---
print_step "Reloading systemd and enabling Nexpose Console..."
run_cmd "sudo systemctl daemon-reload || true"
run_cmd "sudo systemctl enable --now nexposeconsole.service || true"
# --- Verify console successfully starts with FIPS/Federal ---
print_step "Verifying FIPS/Federal mode in logs (polling)..."
LOG="/opt/rapid7/nexpose/nsc/logs/nsc.log"
MAX_WAIT_SECONDS=180
POLL_INTERVAL=10
ELAPSED=0
MARK_FED_TRUE="Console is a Federal instance = true"
MARK_FIPS_TRUE="Console FIPS Mode switched on = true"
MARK_FED_FALSE="Console is a Federal instance = false"
MARK_FIPS_FALSE="Console FIPS Mode switched on = false"
while (( ELAPSED < MAX_WAIT_SECONDS )); do
if [[ -f "$LOG" ]]; then
if sudo grep -qF "$MARK_FED_FALSE" "$LOG" || sudo grep -qF "$MARK_FIPS_FALSE" "$LOG"; then
fail "Detected explicit false markers in log. Aborting."
echo -e "${C_GRAY}"
sudo grep -nE "Console is a Federal instance = |Console FIPS Mode switched on = " "$LOG" | tail -n 100 || true
echo -e "${C_RESET}"
exit 1
fi
if sudo grep -qF "$MARK_FED_TRUE" "$LOG" && sudo grep -qF "$MARK_FIPS_TRUE" "$LOG"; then
ok "Verified: Federal + FIPS active."
exit 0
fi
fi
sleep "$POLL_INTERVAL"
ELAPSED=$((ELAPSED + POLL_INTERVAL))
done
fail "Did not detect both Federal=true and FIPS=true within ${MAX_WAIT_SECONDS}s."
warn "Suggested checks:"
warn " - sudo systemctl status nexposeconsole.service"
warn " - sudo tail -n 200 $LOG"
exit 1