diff --git a/deploy-exporter.sh b/deploy-exporter.sh index cbe721b..68f4fdf 100755 --- a/deploy-exporter.sh +++ b/deploy-exporter.sh @@ -1,7 +1,7 @@ #!/bin/bash ################################################################################ # Script Name: deploy-exporter.sh -# Version: 1.0 +# Version: 1.1 # Description: Deployment tool for Prometheus exporters from mylinux.work. # Downloads, installs, configures cron jobs, validates output, # and manages lifecycle (install, update, remove, status) for @@ -38,6 +38,18 @@ INSTALL_DIR="/usr/local/bin" CRON_DIR="/etc/cron.d" TEXTFILE_DIR="/var/lib/node_exporter" +# Detect noexec /tmp — fall back to /usr/local/src for staging +STAGE_DIR="/tmp" +_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) +if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src" + rm -f "$_exec_test" +else + STAGE_DIR="/usr/local/src" +fi + # ============================================================================ # AVAILABLE EXPORTERS # ============================================================================ @@ -328,7 +340,7 @@ install_one() { log "Installing ${name}..." - temp_file=$(mktemp "/tmp/${name}.XXXXXX") + temp_file=$(mktemp "${STAGE_DIR}/${name}.XXXXXX") if ! download "$url" "$temp_file"; then rm -f "$temp_file" err "Failed to download ${url}" @@ -503,7 +515,7 @@ cmd_update() { local url="${BASE_URL}/${name}.sh" local temp_file - temp_file=$(mktemp "/tmp/${name}.XXXXXX") + temp_file=$(mktemp "${STAGE_DIR}/${name}.XXXXXX") if ! download "$url" "$temp_file"; then rm -f "$temp_file" diff --git a/install-bot-monitor.sh b/install-bot-monitor.sh index 80079cc..1c38622 100644 --- a/install-bot-monitor.sh +++ b/install-bot-monitor.sh @@ -1,7 +1,7 @@ #!/bin/bash ################################################################################ # Script Name: install-bot-monitor.sh -# Version: 1.1 +# Version: 1.2 # Description: Install the bot-monitor script, known agents whitelist, and # daily cron job. Detects unknown user agents in web server logs # and sends alerts via ntfy and/or Prometheus textfile metrics. @@ -375,7 +375,19 @@ step "Installing bot-monitor script" SCRIPT_FILE="/usr/local/bin/bot-monitor.sh" -cat > /tmp/bot-monitor.sh.tmp << 'SCRIPTEOF' +# Detect noexec /tmp — fall back to /usr/local/src +STAGE_DIR="/tmp" +_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) +if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src" + rm -f "$_exec_test" +else + STAGE_DIR="/usr/local/src" +fi + +cat > ${STAGE_DIR}/bot-monitor.sh.tmp << 'SCRIPTEOF' #!/bin/bash # /usr/local/bin/bot-monitor.sh # Detects unknown user agents in yesterday's web server logs. @@ -478,12 +490,12 @@ find "$STATE_DIR" -name "unknown-*.txt" -mtime +30 -delete 2>/dev/null || true SCRIPTEOF # Replace placeholders with actual values -sed -i "s|__LOG_DIR__|${LOG_DIR}|g" /tmp/bot-monitor.sh.tmp -sed -i "s|__LOG_PATTERN__|${LOG_PATTERN}|g" /tmp/bot-monitor.sh.tmp -sed -i "s|__NTFY_URL__|${NTFY_URL}|g" /tmp/bot-monitor.sh.tmp -sed -i "s|__TEXTFILE_DIR__|${TEXTFILE_DIR}|g" /tmp/bot-monitor.sh.tmp -sed -i "s|__TEXTFILE_ENABLED__|${TEXTFILE_ENABLED}|g" /tmp/bot-monitor.sh.tmp -sed -i "s|__MIN_REQUESTS__|${MIN_REQUESTS}|g" /tmp/bot-monitor.sh.tmp +sed -i "s|__LOG_DIR__|${LOG_DIR}|g" ${STAGE_DIR}/bot-monitor.sh.tmp +sed -i "s|__LOG_PATTERN__|${LOG_PATTERN}|g" ${STAGE_DIR}/bot-monitor.sh.tmp +sed -i "s|__NTFY_URL__|${NTFY_URL}|g" ${STAGE_DIR}/bot-monitor.sh.tmp +sed -i "s|__TEXTFILE_DIR__|${TEXTFILE_DIR}|g" ${STAGE_DIR}/bot-monitor.sh.tmp +sed -i "s|__TEXTFILE_ENABLED__|${TEXTFILE_ENABLED}|g" ${STAGE_DIR}/bot-monitor.sh.tmp +sed -i "s|__MIN_REQUESTS__|${MIN_REQUESTS}|g" ${STAGE_DIR}/bot-monitor.sh.tmp if [[ "$DRY_RUN" == "true" ]]; then echo " Would install: ${SCRIPT_FILE}" @@ -497,7 +509,7 @@ else cp "$SCRIPT_FILE" "${SCRIPT_FILE}.bak.$(date +%s)" warn "Existing script backed up" fi - mv /tmp/bot-monitor.sh.tmp "$SCRIPT_FILE" + mv ${STAGE_DIR}/bot-monitor.sh.tmp "$SCRIPT_FILE" chmod +x "$SCRIPT_FILE" info "Installed: ${SCRIPT_FILE}" fi diff --git a/install-node-exporter.sh b/install-node-exporter.sh index c42ed21..1d1a084 100644 --- a/install-node-exporter.sh +++ b/install-node-exporter.sh @@ -9,7 +9,7 @@ set -euo pipefail #### Author: Phil Connor #### #### Contact: contact@mylinux.work #### #### License: MIT #### -#### Version: 1.1 #### +#### Version: 1.2 #### #### #### #### Usage: ./install-node-exporter.sh [OPTIONS] #### ############################################################# @@ -208,7 +208,20 @@ create_service_user() { download_and_install() { local version="$1" - TMPDIR=$(mktemp -d /tmp/node-exporter-install-XXXXXX) + # Detect noexec /tmp — fall back to /usr/local/src + local stage_dir="/tmp" + local _exec_test + _exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) + if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || stage_dir="/usr/local/src" + rm -f "$_exec_test" + else + stage_dir="/usr/local/src" + fi + + TMPDIR=$(mktemp -d "${stage_dir}/node-exporter-install-XXXXXX") local tarball="node_exporter-${version}.linux-${ARCH}.tar.gz" local url="https://github.com/prometheus/node_exporter/releases/download/v${version}/${tarball}" diff --git a/install-ntfy-server.sh b/install-ntfy-server.sh index f76396c..d290649 100644 --- a/install-ntfy-server.sh +++ b/install-ntfy-server.sh @@ -7,7 +7,7 @@ #### Author: Phil Connor #### #### Contact: contact@mylinux.work #### #### License: MIT #### -#### Version: 1.0 #### +#### Version: 1.1 #### #### #### #### Usage: sudo ./install-ntfy-server.sh #### ############################################################# @@ -28,6 +28,18 @@ if [[ $EUID -ne 0 ]]; then exit 1 fi +# Detect noexec /tmp — fall back to /usr/local/src +STAGE_DIR="/tmp" +_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) +if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src" + rm -f "$_exec_test" +else + STAGE_DIR="/usr/local/src" +fi + echo "=== Installing ntfy v${NTFY_VERSION} ===" # Create ntfy user @@ -43,13 +55,13 @@ chown "$NTFY_USER:$NTFY_USER" "$NTFY_DIR" # Download and install ntfy echo "Downloading ntfy..." -rm -rf /tmp/ntfy_extract -mkdir -p /tmp/ntfy_extract -wget -q -O /tmp/ntfy.tar.gz "https://github.com/binwiederhier/ntfy/releases/download/v${NTFY_VERSION}/ntfy_${NTFY_VERSION}_linux_amd64.tar.gz" -tar -xzf /tmp/ntfy.tar.gz -C /tmp/ntfy_extract -find /tmp/ntfy_extract -name "ntfy" -type f -exec mv {} /usr/local/bin/ntfy \; +rm -rf ${STAGE_DIR}/ntfy_extract +mkdir -p ${STAGE_DIR}/ntfy_extract +wget -q -O ${STAGE_DIR}/ntfy.tar.gz "https://github.com/binwiederhier/ntfy/releases/download/v${NTFY_VERSION}/ntfy_${NTFY_VERSION}_linux_amd64.tar.gz" +tar -xzf ${STAGE_DIR}/ntfy.tar.gz -C ${STAGE_DIR}/ntfy_extract +find ${STAGE_DIR}/ntfy_extract -name "ntfy" -type f -exec mv {} /usr/local/bin/ntfy \; chmod +x /usr/local/bin/ntfy -rm -rf /tmp/ntfy.tar.gz /tmp/ntfy_extract +rm -rf ${STAGE_DIR}/ntfy.tar.gz ${STAGE_DIR}/ntfy_extract # Verify installation echo "Verifying installation..." diff --git a/install-prometheus-stack.sh b/install-prometheus-stack.sh index 21fbb66..32e48f0 100755 --- a/install-prometheus-stack.sh +++ b/install-prometheus-stack.sh @@ -9,7 +9,7 @@ set -euo pipefail #### Author: Phil Connor #### #### Contact: contact@mylinux.work #### #### License: MIT #### -#### Version: 3.1 #### +#### Version: 3.2 #### #### #### #### Usage: ./install-prometheus-stack.sh [OPTIONS] #### ############################################################# @@ -105,9 +105,21 @@ CONFIG FILE FORMAT: EOF } +# Detect noexec /tmp — fall back to /usr/local/src +STAGE_DIR="/tmp" +_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) +if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src" + rm -f "$_exec_test" +else + STAGE_DIR="/usr/local/src" +fi + cleanup() { - if [[ -d "/tmp/prometheus-install-$$" ]]; then - rm -rf "/tmp/prometheus-install-$$" + if [[ -d "${STAGE_DIR}/prometheus-install-$$" ]]; then + rm -rf "${STAGE_DIR}/prometheus-install-$$" fi } @@ -262,7 +274,7 @@ install_prometheus() { return fi - local workdir="/tmp/prometheus-install-$$/prometheus" + local workdir="${STAGE_DIR}/prometheus-install-$$/prometheus" mkdir -p "$workdir" cd "$workdir" @@ -417,7 +429,7 @@ install_node_exporter() { return fi - local workdir="/tmp/prometheus-install-$$/node_exporter" + local workdir="${STAGE_DIR}/prometheus-install-$$/node_exporter" mkdir -p "$workdir" cd "$workdir" @@ -494,7 +506,7 @@ install_blackbox() { return fi - local workdir="/tmp/prometheus-install-$$/blackbox" + local workdir="${STAGE_DIR}/prometheus-install-$$/blackbox" mkdir -p "$workdir" cd "$workdir" @@ -686,7 +698,7 @@ install_loki() { return fi - local workdir="/tmp/prometheus-install-$$/loki" + local workdir="${STAGE_DIR}/prometheus-install-$$/loki" mkdir -p "$workdir" cd "$workdir" @@ -830,7 +842,7 @@ install_alloy() { return fi - local workdir="/tmp/prometheus-install-$$/alloy" + local workdir="${STAGE_DIR}/prometheus-install-$$/alloy" mkdir -p "$workdir" cd "$workdir" @@ -1243,7 +1255,7 @@ install_alertmanager() { return fi - local workdir="/tmp/prometheus-install-$$/alertmanager" + local workdir="${STAGE_DIR}/prometheus-install-$$/alertmanager" mkdir -p "$workdir" cd "$workdir" @@ -1337,7 +1349,7 @@ install_mysql_exporter() { return fi - local workdir="/tmp/prometheus-install-$$/mysql_exporter" + local workdir="${STAGE_DIR}/prometheus-install-$$/mysql_exporter" mkdir -p "$workdir" cd "$workdir" diff --git a/install-snort.sh b/install-snort.sh index 642d05c..ab6dcd7 100644 --- a/install-snort.sh +++ b/install-snort.sh @@ -8,7 +8,7 @@ # Contact: contact@mylinux.work # Website: https://mylinux.work # License: MIT -# Version: 1.01 +# Version: 1.02 # # Usage: # sudo ./install-snort.sh @@ -39,6 +39,18 @@ DRY_RUN=false UNINSTALL=false SKIP_BUILD=false +# Detect noexec /tmp — fall back to /usr/local/src +STAGE_DIR="/tmp" +_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) +if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src" + rm -f "$_exec_test" +else + STAGE_DIR="/usr/local/src" +fi + # Colors RED='\033[0;31m' GREEN='\033[0;32m' @@ -201,7 +213,7 @@ install_dependencies() { build_libdaq() { log_step "Building libdaq $DAQ_VERSION..." - local build_dir="/tmp/snort-build" + local build_dir="${STAGE_DIR}/snort-build" mkdir -p "$build_dir" cd "$build_dir" @@ -224,7 +236,7 @@ build_libdaq() { build_snort() { log_step "Building Snort $SNORT_VERSION..." - local build_dir="/tmp/snort-build" + local build_dir="${STAGE_DIR}/snort-build" mkdir -p "$build_dir" cd "$build_dir" @@ -336,16 +348,16 @@ download_rules() { if [[ "$COMMUNITY_RULES" == true ]]; then log_info "Downloading community rules..." local community_url="https://www.snort.org/downloads/community/snort3-community-rules.tar.gz" - wget -q "$community_url" -O /tmp/snort3-community-rules.tar.gz || { + wget -q "$community_url" -O ${STAGE_DIR}/snort3-community-rules.tar.gz || { log_warn "Failed to download community rules — trying alternative URL" wget -q "https://www.snort.org/downloads/community/community-rules.tar.gz" \ - -O /tmp/snort3-community-rules.tar.gz || { + -O ${STAGE_DIR}/snort3-community-rules.tar.gz || { log_error "Cannot download community rules" return 1 } } - tar xzf /tmp/snort3-community-rules.tar.gz -C /tmp/ - find /tmp/ -name '*.rules' -path '*community*' -exec cp {} "$RULE_DIR/" \; + tar xzf ${STAGE_DIR}/snort3-community-rules.tar.gz -C ${STAGE_DIR}/ + find ${STAGE_DIR}/ -name '*.rules' -path '*community*' -exec cp {} "$RULE_DIR/" \; log_info "Community rules installed to $RULE_DIR/" fi @@ -355,11 +367,11 @@ download_rules() { else log_info "Downloading registered rules with Oinkcode..." local reg_url="https://www.snort.org/reg-rules/snortrules-snapshot-31840.tar.gz/$OINKCODE" - wget -q "$reg_url" -O /tmp/snort-registered-rules.tar.gz || { + wget -q "$reg_url" -O ${STAGE_DIR}/snort-registered-rules.tar.gz || { log_error "Failed to download registered rules (check Oinkcode)" return 1 } - tar xzf /tmp/snort-registered-rules.tar.gz -C "$RULE_DIR/" + tar xzf ${STAGE_DIR}/snort-registered-rules.tar.gz -C "$RULE_DIR/" log_info "Registered rules installed to $RULE_DIR/" fi fi diff --git a/update-prometheus-stack.sh b/update-prometheus-stack.sh index 4c80d94..8eb0153 100755 --- a/update-prometheus-stack.sh +++ b/update-prometheus-stack.sh @@ -35,14 +35,26 @@ set -euo pipefail ## ## ## Author: Phil Connor ## ## Contact: pconnor@ara.com ## -## Version: 1.01 ## +## Version: 1.02 ## ########################################################################## BINDIR="/usr/local/bin" PROMDIR="/etc/prometheus" BACKUPDIR="${PROMDIR}/backups" LOGFILE="/var/log/prometheus-update.log" -TMPDIR_BASE="/tmp/prometheus-update-$$" +# Detect noexec /tmp — fall back to /usr/local/src +STAGE_DIR="/tmp" +_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null) +if [[ -n "$_exec_test" ]]; then + printf '#!/bin/sh\nexit 0\n' > "$_exec_test" + chmod +x "$_exec_test" + "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src" + rm -f "$_exec_test" +else + STAGE_DIR="/usr/local/src" +fi + +TMPDIR_BASE="${STAGE_DIR}/prometheus-update-$$" CHECK_ONLY=false BACKUP_ONLY=false FORCE=false