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
111 lines
6.2 KiB
Bash
111 lines
6.2 KiB
Bash
#!/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'
|