gendesign/ops/selectel-audit.sh
lekss361 536137d460
All checks were successful
Deploy Infra Host / sync-infra-host (push) Successful in 2s
Deploy / changes (push) Successful in 9s
Deploy Trade-In / changes (push) Successful in 12s
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Successful in 52s
Deploy / build-worker (push) Successful in 52s
Deploy / build-frontend (push) Successful in 52s
Deploy Trade-In / build-browser (push) Successful in 41s
Deploy Obsidian / deploy-obsidian (push) Successful in 2m15s
Deploy / deploy (push) Successful in 1m53s
Deploy Trade-In / build-frontend (push) Successful in 2m44s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 12s
Deploy Trade-In / test (push) Successful in 4m8s
Deploy Trade-In / build-backend (push) Successful in 47s
Deploy Trade-In / deploy (push) Successful in 1m42s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 9s
feat(ci): деплой проверяет, к тому ли хосту подключился (#3079)
2026-08-24 16:36:50 +00:00

111 lines
6.2 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Аудит нового выделенного сервера ДО того, как на него что-либо поставлено.
#
# Только чтение — ничего не меняет. Задача одна: собрать факты, по которым
# принимается решение «работаем на этой установке» или «переставляем ОС».
#
# Главный вопрос — RAID. На AR32-NVMe два диска по 1 ТБ. Если они отданы
# по отдельности или собраны в RAID0, смерть одного диска = потеря всего,
# а память на этой платформе non-ECC. Переставить ОС можно только пока
# сервер пустой, поэтому проверка идёт первой и до всего остального.
#
# Запуск: ssh <host> 'bash -s' < ops/selectel-audit.sh
set -uo pipefail
section() { printf '\n=== %s ===\n' "$1"; }
section "Идентификация"
. /etc/os-release 2>/dev/null && echo "OS: ${PRETTY_NAME:-unknown}"
echo "Kernel: $(uname -r)"
echo "Hostname: $(hostname)"
echo "Uptime: $(uptime -p 2>/dev/null || true)"
section "CPU / память"
lscpu 2>/dev/null | grep -E '^(Model name|CPU\(s\)|Thread|Core|Socket|CPU max MHz)' || nproc
free -h | head -2
echo "--- ECC (пусто = не-ECC либо недоступно из ОС) ---"
dmidecode -t memory 2>/dev/null | grep -iE 'error correction|^\s+Type:' | sort -u | head -5 \
|| echo "dmidecode недоступен (нужен root)"
section "ДИСКИ — ключевой вопрос"
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,MODEL
echo "--- программный RAID ---"
if [ -f /proc/mdstat ]; then cat /proc/mdstat; else echo "/proc/mdstat отсутствует"; fi
echo "--- аппаратный RAID / NVMe ---"
lspci 2>/dev/null | grep -iE 'raid|nvme' || echo "контроллеров RAID не видно"
nvme list 2>/dev/null || echo "nvme-cli не установлен"
echo "--- LVM ---"
pvs 2>/dev/null; vgs 2>/dev/null; lvs 2>/dev/null
echo "--- монтирование ---"
df -hT -x tmpfs -x devtmpfs
echo
echo ">>> ВЕРДИКТ ПО ДИСКАМ читать так:"
echo ">>> raid1 / mirror в mdstat → зеркало есть, можно работать"
echo ">>> raid0 / linear / дисков нет → зеркала НЕТ, переставить ОС до установки чего-либо"
echo ">>> один диск в df, второй пуст → второй не используется, решить как задействовать"
section "Сеть"
ip -brief addr show | grep -v '^lo'
ip route | head -5
echo "--- DNS ---"
grep -E '^nameserver' /etc/resolv.conf 2>/dev/null | head -3
section "Что уже слушает"
ss -tulpn 2>/dev/null | grep LISTEN || netstat -tulpn 2>/dev/null | grep LISTEN
section "Безопасность — текущее состояние"
echo "--- sshd (значимые директивы) ---"
sshd -T 2>/dev/null | grep -E '^(permitrootlogin|passwordauthentication|pubkeyauthentication|port|permitemptypasswords)' \
|| grep -E '^\s*(PermitRootLogin|PasswordAuthentication|Port)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/null
echo "--- файрвол ---"
# verbose + numbered вместо голого `ufw status`: по verbose видно политику по
# умолчанию, по numbered — порядок правил и их номера. И то и другое нужно,
# чтобы после ops/selectel-ci-access.sh проверить две вещи сразу: что узкое
# правило для адреса раннера (#3029) добавилось и что общее правило для ssh
# пока живо (до переезда оно снимается ТОЛЬКО вручную и осознанно).
ufw status verbose 2>/dev/null || echo "ufw не установлен"
ufw status numbered 2>/dev/null
nft list ruleset 2>/dev/null | head -20 || iptables -S 2>/dev/null | head -20
echo "--- пользователи с shell ---"
awk -F: '$7 !~ /(nologin|false)$/ {print $1" "$7}' /etc/passwd
echo "--- ключи доступа (тела ключей НЕ печатаются) ---"
# Чем проверяется результат ops/selectel-ci-access.sh (#3029): видно, сколько
# ключей у учётки, чем они ограничены и который из них CI-шный. Печатаются
# только отпечаток, комментарий и опции — по ним ключ опознаётся, но
# воспроизвести его нельзя, поэтому вывод аудита остаётся безопасным для
# пересылки. Отпечаток тут тот же, что пишет sshd в auth.log при входе, так
# что строки отсюда и из журнала сопоставляются напрямую.
for ak in /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys; do
[ -f "$ak" ] || continue
echo " $ak:"
n=0
while IFS= read -r akline; do
case "$akline" in ''|'#'*) continue ;; esac
n=$((n+1))
akfp="$(printf '%s\n' "$akline" | ssh-keygen -lf - 2>/dev/null | awk '{$1=""; sub(/^ /,""); print}')"
akopt="$(printf '%s\n' "$akline" | awk '{o="";for(i=1;i<=NF;i++){if($i ~ /^(ssh-|ecdsa-sha2-|sk-)/)break; o=o (o==""?"":" ") $i} print (o==""?"(без ограничений)":o)}')"
printf ' %d) %s\n опции: %s\n' "$n" "${akfp:-<не разобран>}" "$akopt"
done < "$ak"
if [ "$n" -eq 0 ]; then echo " (пусто)"; fi
done
section "Swap / sysctl"
swapon --show || echo "swap отсутствует"
sysctl vm.swappiness vm.overcommit_memory 2>/dev/null
section "Уже установленное ПО"
for b in docker containerd git curl ufw fail2ban-server unattended-upgrade; do
if command -v "$b" >/dev/null 2>&1; then
printf '%-22s %s\n' "$b" "$($b --version 2>/dev/null | head -1)"
else
printf '%-22s %s\n' "$b" "НЕ установлен"
fi
done
section "Время"
timedatectl 2>/dev/null | head -5 || date
printf '\n=== Аудит закончен ===\n'