diff --git a/check/zadanie2/br-rtr.sh b/check/zadanie2/br-rtr.sh new file mode 100644 index 0000000..177aa8e --- /dev/null +++ b/check/zadanie2/br-rtr.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# ============================================================ +# ПРОВЕРКА ЗАДАНИЯ 2 — BR-RTR: DNAT (8080/2027 -> BR-SRV), +# chrony-клиент (сервер = ISP) +# (только читает состояние; iptables требует root) +# ============================================================ + +NAME="br-rtr" +LOG="check_${NAME}_z2.txt" + +OK=0; FAIL=0; SKIP=0 +ok() { echo "[OK] $1"; OK=$((OK+1)); } +fail() { echo "[FAIL] $1 — $2"; FAIL=$((FAIL+1)); } +skip() { echo "[ПРОПУЩЕНО] $1"; SKIP=$((SKIP+1)); } +root_or_skip() { if [[ $EUID -ne 0 ]]; then skip "$1 (нужен root)"; return 1; fi; return 0; } +check_var() { if [[ -z "${!2}" ]]; then skip "$1 — не задано $2"; return 1; fi; return 0; } + +# ================= ПЕРЕМЕННЫЕ (заполните для проверки) ================= +BR_SRV_IP="" # адрес BR-SRV +TESTAPP_PORT="8080" # порт testapp +SSH_PORT="2027" +NTP_ADDR="" # адрес ISP (источник NTP) + +main () { +echo "=== Проверка задания 2: BR-RTR (DNAT + chrony-клиент) ===" + +if root_or_skip "правила DNAT (iptables)"; then + NAT=$(iptables -t nat -S PREROUTING 2>/dev/null) + check_var "адрес BR-SRV" BR_SRV_IP && { + if grep -qF "DNAT --to-destination $BR_SRV_IP:$TESTAPP_PORT" <<<"$NAT" \ + || grep -qF "DNAT --to $BR_SRV_IP:$TESTAPP_PORT" <<<"$NAT"; then + ok "проброс 8080 -> $BR_SRV_IP:$TESTAPP_PORT" + else fail "проброс 8080" "нет DNAT строки в: $NAT"; fi + } + check_var "адрес BR-SRV" BR_SRV_IP && { + if grep -qF "DNAT --to-destination $BR_SRV_IP:$SSH_PORT" <<<"$NAT" \ + || grep -qF "DNAT --to $BR_SRV_IP:$SSH_PORT" <<<"$NAT"; then + ok "проброс 2027 -> $BR_SRV_IP:$SSH_PORT" + else fail "проброс 2027" "нет DNAT строки в: $NAT"; fi + } +fi + +# --- chrony-клиент: источник = адрес ISP --- +check_var "источник NTP" NTP_ADDR && + if command -v chronyc &>/dev/null; then + if chronyc sources 2>/dev/null | grep -qF "$NTP_ADDR"; then + ok "NTP источник = $NTP_ADDR" + else fail "NTP источник" "адрес $NTP_ADDR не найден в chronyc sources: $(chronyc sources 2>&1)"; fi + else skip "NTP источник — chronyc не найден (ПРОВЕРИТЬ пакет chrony)"; fi + +echo "" +echo "=== Проверить вручную ===" +echo " — chronyc tracking (синхронизировано?)" +echo " — с ISP: nc -zv <адрес BR-RTR на линке> 2027 и 8080" + +echo "" +echo "=== Итог: OK=$OK FAIL=$FAIL ПРОПУЩЕНО=$SKIP ===" +[[ $FAIL -eq 0 ]] +} +main 2>&1 | tee "$LOG" +STATUS=${PIPESTATUS[0]} +echo "Лог сохранён: $LOG" +exit $STATUS diff --git a/check/zadanie2/br-srv.sh b/check/zadanie2/br-srv.sh new file mode 100644 index 0000000..aa5b940 --- /dev/null +++ b/check/zadanie2/br-srv.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# ============================================================ +# ПРОВЕРКА ЗАДАНИЯ 2 — BR-SRV: Samba DC, Ansible, Docker +# (только читает состояние; samba-tool/docker/ansible требуют root) +# ЕДИНСТВЕННАЯ запись — нет: все команды только для чтения +# (docker ps, samba-tool user list, ansible ping — информационный модуль). +# ============================================================ + +NAME="br-srv" +LOG="check_${NAME}_z2.txt" + +OK=0; FAIL=0; SKIP=0 +ok() { echo "[OK] $1"; OK=$((OK+1)); } +fail() { echo "[FAIL] $1 — $2"; FAIL=$((FAIL+1)); } +skip() { echo "[ПРОПУЩЕНО] $1"; SKIP=$((SKIP+1)); } +root_or_skip() { if [[ $EUID -ne 0 ]]; then skip "$1 (нужен root)"; return 1; fi; return 0; } +check_var() { if [[ -z "${!2}" ]]; then skip "$1 — не задано $2"; return 1; fi; return 0; } + +# ================= ПЕРЕМЕННЫЕ (заполните для проверки) ================= +HQ_USERS_COUNT="5" # по заданию hquser1..5 +HQ_GROUP="hq" +MIN_PWD_LENGTH="8" # политика по заданию +LOCKOUT_ATTEMPTS="5" # блокировка по заданию +# sudo-проверка группы hq выполняется на HQ-CLI (check/zadanie2/hq-cli.sh) + +main () { +echo "=== Проверка задания 2: BR-SRV (Samba/Ansible/Docker) ===" + +# --- 1. Пользователи hquser1..5 --- +if root_or_skip "samba-tool (требует root)"; then + if ! command -v samba-tool &>/dev/null; then + skip "Samba — samba-tool не найден (ПРОВЕРИТЬ установку samba-dc)" + else + USER_LIST=$(samba-tool user list 2>/dev/null) + COUNT_OK=0 + for i in $(seq 1 "$HQ_USERS_COUNT"); do + if grep -qx "hquser${i}" <<<"$USER_LIST"; then COUNT_OK=$((COUNT_OK+1)); + else fail "пользователь hquser${i}" "не найден в списке домена"; fi + done + [[ $COUNT_OK -eq $HQ_USERS_COUNT ]] && ok "пользователи hquser1..$HQ_USERS_COUNT созданы ($COUNT_OK)" + # --- группа hq --- + if samba-tool group list 2>/dev/null | grep -qx "$HQ_GROUP"; then + ok "группа $HQ_GROUP существует" + MEMBERS=$(samba-tool group listmembers "$HQ_GROUP" 2>/dev/null | grep -c "^hquser") + if [[ $MEMBERS -eq $HQ_USERS_COUNT ]]; then ok "в группе $HQ_GROUP все $HQ_USERS_COUNT пользователей" + else fail "состав группы $HQ_GROUP" "ожидалось $HQ_USERS_COUNT hquser*, найдено $MEMBERS: $(samba-tool group listmembers "$HQ_GROUP" 2>&1)"; fi + else fail "группа $HQ_GROUP" "группа не найдена"; fi + # --- политика паролей --- + POLICY=$(samba-tool domain passwordsettings show 2>/dev/null) + if grep -Eqi "minimum password length.*$MIN_PWD_LENGTH" <<<"$POLICY"; then + ok "минимальная длина пароля = $MIN_PWD_LENGTH" + else fail "длина пароля" "ожидалось $MIN_PWD_LENGTH: $(echo "$POLICY" | grep -i length)"; fi + if grep -Eqi "bad password count.*$LOCKOUT_ATTEMPTS|lockout.*$LOCKOUT_ATTEMPTS" <<<"$POLICY"; then + ok "блокировка после $LOCKOUT_ATTEMPTS неудачных попыток" + else fail "блокировка учётной записи" "ожидалось $LOCKOUT_ATTEMPTS: $(echo "$POLICY" | grep -Ei 'lockout|attempt')"; fi + fi +fi + +# --- 2. Ansible: ansible all -m ping (все pong) --- +if command -v ansible &>/dev/null; then + PING_OUT=$(ansible all -m ping 2>&1) + N_OK=$(grep -c "SUCCESS" <<<"$PING_OUT") + N_FAILS=$(grep -c "UNREACHABLE\|failed" <<<"$PING_OUT") + if [[ $N_OK -ge 4 && $N_FAILS -eq 0 ]]; then ok "ansible all -m ping: $N_OK машин ответили" + else fail "ansible ping" "успешных $N_OK (ожидалось ≥4), проблем $N_FAILS"; fi +else + skip "ansible — не установлен/не в PATH (инвентарь в /etc/ansible)" +fi + +# --- 3. Docker: контейнеры и порт 8080 --- +if root_or_skip "docker ps / сетевая проверка порта"; then + if command -v docker &>/dev/null; then + CWEB=$(docker ps 2>/dev/null | grep -ciE "site|web|app") + CDB=$(docker ps 2>/dev/null | grep -ciE "mariadb|db") + if [[ $CWEB -ge 1 && $CDB -ge 1 ]]; then + ok "docker: найдено $CWEB контейнер(ов) приложения, $CDB — БД" + else fail "docker контейнеры" "ожидалось приложение + mariadb: $(docker ps 2>&1)"; fi + if curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:8080/" 2>/dev/null | grep -q "200\|301\|302\|401"; then + ok "testapp отвечает на порт 8080 (curl)" + else fail "testapp порт 8080" "нет ответа от локального порта 8080"; fi + else + skip "docker — команда не найдена (ПРОВЕРИТЬ пакет docker на РЕД ОС 8)" + fi +fi + +echo "" +echo "=== Проверить вручную ===" +echo " — testapp доступен на 8080 извне: с ISP curl http://<линк к BR-RTR>:8080" +echo " — вход пользователей группы hq на HQ-CLI (см. check/zadanie2/hq-cli.sh)" + +echo "" +echo "=== Итог: OK=$OK FAIL=$FAIL ПРОПУЩЕНО=$SKIP ===" +[[ $FAIL -eq 0 ]] +} +main 2>&1 | tee "$LOG" +STATUS=${PIPESTATUS[0]} +echo "Лог сохранён: $LOG" +exit $STATUS diff --git a/check/zadanie2/hq-cli.sh b/check/zadanie2/hq-cli.sh new file mode 100644 index 0000000..4ccc452 --- /dev/null +++ b/check/zadanie2/hq-cli.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# ============================================================ +# ПРОВЕРКА ЗАДАНИЕ 2 — HQ-CLI: automount NFS, chrony, домен, sudo +# для группы hq (только cat/grep/id), Яндекс Браузер +# ЕДИНСТВЕННЫЕ попытка записи — временный файл в NFS (см. пункт 2, +# создаётся и сразу удаляется). +# ============================================================ + +NAME="hq-cli" +LOG="check_${NAME}_z2.txt" + +OK=0; FAIL=0; SKIP=0 +ok() { echo "[OK] $1"; OK=$((OK+1)); } +fail() { echo "[FAIL] $1 — $2"; FAIL=$((FAIL+1)); } +skip() { echo "[ПРОПУЩЕНО] $1"; SKIP=$((SKIP+1)); } +root_or_skip() { if [[ $EUID -ne 0 ]]; then skip "$1 (нужен root)"; return 1; fi; return 0; } +check_var() { if [[ -z "${!2}" ]]; then skip "$1 — не задано $2"; return 1; fi; return 0; } +expect_eq() { if [[ "$3" == "$2" ]]; then ok "$1"; else fail "$1" "ожидалось '$2', получено '$3'"; fi; } + +# ================= ПЕРЕМЕННЫЕ (заполните для проверки) ================= +NFS_MOUNT="/mnt/nfs" # точка автомонтирования по заданию +NFS_SERVER="" # адрес HQ-SRV (проверка записи в auto.nfs) +HQ_USER_TEST="hquser1" # пользователь домена для проверки входа +SUDO_CMDS="/usr/bin/cat /usr/bin/grep /usr/bin/id" # разрешённый список +NTP_ADDR="" # адрес ISP (источник NTP) +BROWSER_PATTERN="yandex" # ищемся через dnf list installed + +main () { +echo "=== Проверка задания 2: HQ-CLI ===" + +# --- 1. Автомонтирование NFS в /mnt/nfs --- +if root_or_skip "конфиг autofs"; then + if grep -Eq "[[:space:]]*/mnt[[:space:]]+" /etc/auto.master 2>/dev/null; then + ok "auto.master: карта для /mnt присутствует" + else fail "auto.master" "нет записи для /mnt"; fi + if grep -Eq "^[[:space:]]*[a-zA-Z0-9_-]+[[:space:]]+-rw[[:space:]]+.*$NFS_SERVER" /etc/auto.nfs 2>/dev/null; then + echo "[ИНФО] $(cat /etc/auto.nfs 2>/dev/null)" + SKIP=$((SKIP+1)) + fi +fi +# смонтированную директорию NFS проверяем её содержимым +# (cat вызывает automount триггер — чистое чтение) +# доступный каталог NFS проверяем чтением (оно же триггерит automount) +if [[ -d "$NFS_MOUNT" ]]; then + ok "каталог $NFS_MOUNT доступен (autofs активен)" +else fail "каталог $NFS_MOUNT" "не открылся (autofs/сервер недоступен)"; fi + +# --- 2. ЕДИНСТВЕННЫЙ временный файл в NFS (создаём и сразу удаляем) --- +if [[ -d "$NFS_MOUNT" && -w "$NFS_MOUNT" ]]; then + printf 'tmp %s\n' "$(date +%s)" > "$NFS_MOUNT/.delete-nfs-write-test" + if [[ -f "$NFS_MOUNT/.delete-nfs-write-test" ]]; then + ok "запись в NFS работает (временный файл создан)" + fi + rm -f "$NFS_MOUNT/.delete-nfs-write-test" && ok "временный файл удалён" +else + skip "запись в NFS (не смонтирован $NFS_MOUNT)" +fi + +# --- 3. chrony-клиент: источник = ISP --- +check_var "источник NTP" NTP_ADDR && + if command -v chronyc &>/dev/null; then + if chronyc sources 2>/dev/null | grep -qF "$NTP_ADDR"; then ok "NTP источник = $NTP_ADDR" + else fail "NTP источник" "нет $NTP_ADDR в chronyc sources"; fi + else skip "NTP источник — chronyc не найден"; fi + +# --- 4. Пользователь домена доступен (getent) --- +if getent passwd "$HQ_USER_TEST" &>/dev/null; then + ok "пользователь домена $HQ_USER_TEST доступен на машине (getent)" +else fail "пользователь домена $HQ_USER_TEST" "getent не вернул запись (ввод в домен вручную — MANUAL.md)"; fi + +# --- 5. Sudo для группы hq (только cat/grep/id) --- +if root_or_skip "sudo -l -U $HQ_USER_TEST"; then + SUDO_OUT=$(sudo -l -U "$HQ_USER_TEST" 2>/dev/null) + CMDS_OK=1 + for c in $SUDO_CMDS; do + grep -qw "$(basename "$c")" <<<"$SUDO_OUT" || CMDS_OK=0 + done + if [[ $CMDS_OK -eq 1 ]] && ! grep -q "NOPASSWD: ALL" <<<"$SUDO_OUT"; then + ok "sudo для $HQ_USER_TEST: только $(echo "$SUDO_CMDS" | tr ' ' ',')" + else fail "sudo для $HQ_USER_TEST" "список не совпал (есть ALL или нет всех команд): $(echo "$SUDO_OUT" | grep NOPASSWD)"; fi +fi + +# --- 6. Яндекс Браузер --- +if dnf list installed 2>/dev/null | grep -qiF "$BROWSER_PATTERN"; then + ok "Яндекс Браузер установлен ($(dnf list installed 2>/dev/null | grep -iF "$BROWSER_PATTERN"))" +else fail "Яндекс Браузер" "пакет не найден в dnf list installed"; fi + +echo "" +echo "=== Проверить вручную ===" +echo " — запуск Яндекс Браузера с рабочего стола (если GUI есть)" +echo " — реальные входы доменных пользователей в систему (экран входа/GUI или su -)" + +echo "" +echo "=== Итог: OK=$OK FAIL=$FAIL ПРОПУЩЕНО=$SKIP ===" +[[ $FAIL -eq 0 ]] +} +main 2>&1 | tee "$LOG" +STATUS=${PIPESTATUS[0]} +echo "Лог сохранён: $LOG" +exit $STATUS diff --git a/check/zadanie2/hq-rtr.sh b/check/zadanie2/hq-rtr.sh new file mode 100644 index 0000000..9394ad5 --- /dev/null +++ b/check/zadanie2/hq-rtr.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# ============================================================ +# ПРОВЕРКА ЗАДАНИЯ 2 — HQ-RTR: статический проброс портов (DNAT) +# 8080 -> веб-приложение на HQ-SRV, 2027 -> SSH HQ-SRV +# (только читает состояние; iptables требует root) +# ============================================================ + +NAME="hq-rtr" +LOG="check_${NAME}_z2.txt" + +OK=0; FAIL=0; SKIP=0 +ok() { echo "[OK] $1"; OK=$((OK+1)); } +fail() { echo "[FAIL] $1 — $2"; FAIL=$((FAIL+1)); } +skip() { echo "[ПРОПУЩЕНО] $1"; SKIP=$((SKIP+1)); } +root_or_skip() { if [[ $EUID -ne 0 ]]; then skip "$1 (нужен root)"; return 1; fi; return 0; } +check_var() { if [[ -z "${!2}" ]]; then skip "$1 — не задано $2"; return 1; fi; return 0; } + +# ================= ПЕРЕМЕННЫЕ (заполните для проверки) ================= +HQ_SRV_IP="" # адрес HQ-SRV (без префикса) +WEB_APP_PORT="80" # порт apache на HQ-SRV (как в настройке) +SSH_PORT="2027" # порт ssh на HQ-SRV + +main () { +echo "=== Проверка задания 2: HQ-RTR (DNAT) ===" + +if root_or_skip "правила DNAT (iptables)"; then + NAT=$(iptables -t nat -S PREROUTING 2>/dev/null) + check_var "адрес HQ-SRV" HQ_SRV_IP && { + if grep -qF "DNAT --to-destination $HQ_SRV_IP:$WEB_APP_PORT" <<<"$NAT" \ + || grep -qF "DNAT --to $HQ_SRV_IP:$WEB_APP_PORT" <<<"$NAT"; then + ok "проброс 8080 -> $HQ_SRV_IP:$WEB_APP_PORT" + else fail "проброс 8080" "нет DNAT строки в: $NAT"; fi + } + check_var "адрес HQ-SRV" HQ_SRV_IP && { + if grep -qF "DNAT --to-destination $HQ_SRV_IP:$SSH_PORT" <<<"$NAT" \ + || grep -qF "DNAT --to $HQ_SRV_IP:$SSH_PORT" <<<"$NAT"; then + ok "проброс 2027 -> $HQ_SRV_IP:$SSH_PORT" + else fail "проброс 2027" "нет DNAT строки в: $NAT"; fi + } + POLICY=$(iptables -S FORWARD 2>/dev/null | head -1) + if grep -q "policy" <<<"$POLICY"; then + echo "[ИНФО] $POLICY" + SKIP=$((SKIP+1)) + fi +fi + +echo "" +echo "=== Проверить вручную ===" +echo " — с ISP: curl -I http://<адрес HQ-RTR на линке>:8080 (доступ к веб-приложению извне)" +echo " — с ISP: nc -zv <адрес HQ-RTR на линке> 2027" + +echo "" +echo "=== Итог: OK=$OK FAIL=$FAIL ПРОПУЩЕНО=$SKIP ===" +[[ $FAIL -eq 0 ]] +} +main 2>&1 | tee "$LOG" +STATUS=${PIPESTATUS[0]} +echo "Лог сохранён: $LOG" +exit $STATUS diff --git a/check/zadanie2/hq-srv.sh b/check/zadanie2/hq-srv.sh new file mode 100644 index 0000000..f201823 --- /dev/null +++ b/check/zadanie2/hq-srv.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# ============================================================ +# ПРОВЕРКА ЗАДАНИЯ 2 — HQ-SRV: RAID0, NFS, chrony, apache+mariadb +# (только читает состояние; exportfs/mdadm-детали требуют root) +# ============================================================ + +NAME="hq-srv" +LOG="check_${NAME}_z2.txt" + +OK=0; FAIL=0; SKIP=0 +ok() { echo "[OK] $1"; OK=$((OK+1)); } +fail() { echo "[FAIL] $1 — $2"; FAIL=$((FAIL+1)); } +skip() { echo "[ПРОПУЩЕНО] $1"; SKIP=$((SKIP+1)); } +root_or_skip() { if [[ $EUID -ne 0 ]]; then skip "$1 (нужен root)"; return 1; fi; return 0; } +check_var() { if [[ -z "${!2}" ]]; then skip "$1 — не задано $2"; return 1; fi; return 0; } + +# ================= ПЕРЕМЕННЫЕ (заполните для проверки) ================= +RAID_NAME="md0" # имя массива по заданию +RAID_MOUNT="/raid" # точка монтирования по заданию +NFS_EXPORT="/raid/nfs" # директория экспорта по заданию +NFS_NET="" # сеть HQ-CLI (как в exports) +APACHE_PORT="80" # порт apache +WEB_DB_NAME="webdb" # БД по заданию +WEB_DB_USER="web" # пользователь БД по заданию +WEB_DB_PASS="P@ssw0rd" # пароль пользователя БД по заданию +ISO_WEB_DIR="/mnt/iso/web" # откуда копировались файлы (для справки) +NTP_ADDR="" # адрес ISP (chrony) + +main () { +echo "=== Проверка задания 2: HQ-SRV ===" + +# --- 1. RAID0 (md0) --- +if [[ -e /dev/$RAID_NAME ]] || grep -q "$RAID_NAME" /proc/mdstat 2>/dev/null; then + if grep -A1 "$RAID_NAME" /proc/mdstat 2>/dev/null | grep -q "raid0"; then + ok "массив $RAID_NAME собран уровнем 0" + else fail "уровень $RAID_NAME" "не raid0 в /proc/mdstat: $(grep -A1 "$RAID_NAME" /proc/mdstat 2>/dev/null)"; fi + DISKS=$(grep -A1 "$RAID_NAME" /proc/mdstat 2>/dev/null | head -1 | grep -o "\[2/2\]") + if [[ -n "$DISKS" ]]; then ok "в массиве 2 диска ($DISKS)" + else fail "диски массива" "ожидалось [2/2]: $(grep -A1 "$RAID_NAME" /proc/mdstat)"; fi +else + fail "массив $RAID_NAME" "не существует"; fi + +# --- 2. ФС ext4 и монтирование /raid --- +FSTYP=$(lsblk -no FSTYPE /dev/$RAID_NAME 2>/dev/null) +expect_eq "файловая система $RAID_NAME" "ext4" "$FSTYP" +if mountpoint -q "$RAID_MOUNT" 2>/dev/null; then + ok "$RAID_MOUNT смонтирована" +else fail "$RAID_MOUNT" "не точка монтирования"; fi +if grep -qE " .*$RAID_MOUNT " /etc/fstab 2>/dev/null \ + && grep -E " .*$RAID_MOUNT .*ext4" /etc/fstab &>/dev/null; then + ok "/raid прописан в /etc/fstab" +else fail "/raid в fstab" "нет строки с $RAID_MOUNT (ext4): $(grep -E "raid" /etc/fstab)"; fi + +# --- 3. NFS --- +if grep -qF "$NFS_EXPORT" /etc/exports 2>/dev/null; then + EXPORT_LINE=$(grep -F "$NFS_EXPORT" /etc/exports) + if check_var "сеть HQ-CLI для NFS" NFS_NET && grep -qF "$NFS_NET" <<<"$EXPORT_LINE" \ + && grep -qw "rw" <<<"$EXPORT_LINE"; then + ok "NFS экспорт: $EXPORT_LINE" + else fail "NFS экспорт" "нет rw для $NFS_NET: '$EXPORT_LINE'"; fi +else fail "NFS экспорт $NFS_EXPORT" "нет строки в /etc/exports"; fi +if root_or_skip "exportfs (текущее состояние NFS)"; then + if exportfs -v 2>/dev/null | grep -qF "$NFS_EXPORT"; then + ok "NFS экспорт активен (exportfs)" + else fail "NFS экспорт активен" "нет в exportfs -v"; fi +fi + +# --- 4. chrony-клиент --- +check_var "источник NTP" NTP_ADDR && + if command -v chronyc &>/dev/null; then + if chronyc sources 2>/dev/null | grep -qF "$NTP_ADDR"; then ok "NTP источник = $NTP_ADDR" + else fail "NTP источник" "нет $NTP_ADDR в chronyc sources"; fi + else skip "NTP источник — chronyc не найден (ПРОВЕРИТЬ пакет chrony)"; fi + +# --- 5. apache + mariadb + приложение --- +if systemctl is-active httpd &>/dev/null || systemctl is-active apache2 &>/dev/null; then + ok "веб-сервер apache активен" +else fail "apache" "служба не активна (ПРОВЕРИТЬ имя службы на РЕД ОС 8)"; fi +HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:$APACHE_PORT/" 2>/dev/null) +if [[ "$HTTP_CODE" == "200" ]]; then ok "apache отвечает 200 на порт $APACHE_PORT" +else fail "ответ apache" "ожидалось 200, получено '$HTTP_CODE'"; fi +if [[ -f /var/www/html/index.php && -f /var/www/html/logo.png ]]; then + ok "index.php и logo.png в корне сайта" +else fail "файлы сайта" "нет index.php/logo.png в /var/www/html"; fi + +MYSQL_OUT=$(mysql -u"$WEB_DB_USER" -p"$WEB_DB_PASS" -e "SHOW TABLES;" "$WEB_DB_NAME" 2>&1) +if grep -q "Tables_in" <<<"$MYSQL_OUT"; then + ok "доступ к БД $WEB_DB_NAME под $WEB_DB_USER (таблицы есть)" +else fail "БД $WEB_DB_NAME" "нет таблиц или ошибка подключения: $MYSQL_OUT"; fi + +echo "" +echo "=== Проверить вручную ===" +echo " — страница приложения в браузере (функционал, картинка logo.png)" +echo " — содержимое index.php (учётные данные БД указаны правильно)" +echo " — скриншоты для отчёта: exportfs -v, mdadm --D dev/md0, df -h /raid" + +echo "" +echo "=== Итог: OK=$OK FAIL=$FAIL ПРОПУЩЕНО=$SKIP ===" +[[ $FAIL -eq 0 ]] +} +main 2>&1 | tee "$LOG" +STATUS=${PIPESTATUS[0]} +echo "Лог сохранён: $LOG" +exit $STATUS diff --git a/check/zadanie2/isp.sh b/check/zadanie2/isp.sh new file mode 100644 index 0000000..813fe99 --- /dev/null +++ b/check/zadanie2/isp.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# ============================================================ +# ПРОВЕРКА ЗАДАНИЯ 2 — ISP: chrony-сервер, стратум 5 +# (только читает состояние) +# ============================================================ + +NAME="isp" +LOG="check_${NAME}_z2.txt" + +OK=0; FAIL=0; SKIP=0 +ok() { echo "[OK] $1"; OK=$((OK+1)); } +fail() { echo "[FAIL] $1 — $2"; FAIL=$((FAIL+1)); } +skip() { echo "[ПРОПУЩЕНО] $1"; SKIP=$((SKIP+1)); } +root_or_skip() { if [[ $EUID -ne 0 ]]; then skip "$1 (нужен root)"; return 1; fi; return 0; } +check_var() { if [[ -z "${!2}" ]]; then skip "$1 — не задано $2"; return 1; fi; return 0; } + +# ================= ПЕРЕМЕННЫЕ (заполните для проверки) ================= +CHRONY_CONF="/etc/chrony.conf" # ПРОВЕРИТЬ путь на РЕД ОС 8 +STRATUM_EXPECTED="5" # по заданию 2 п. 4 +ALLOW_NETS="" # сети клиентов, через пробел (как в isp.sh настройки) + +main () { +echo "=== Проверка задания 2: ISP (chrony) ===" + +# --- 1. Стратум 5 --- +if command -v chronyc &>/dev/null; then + GOT_STRATUM=$(chronyc tracking 2>/dev/null | awk '/^Stratum/ {print $2}') + if [[ "$GOT_STRATUM" == "$STRATUM_EXPECTED" ]]; then ok "стратум = $GOT_STRATUM" + else fail "стратум" "ожидалось $STRATUM_EXPECTED, получено '$GOT_STRATUM'"; fi + # служба активна + if systemctl is-active chronyd &>/dev/null; then ok "служба chronyd активна" + else fail "служба chronyd" "не активна (ПРОВЕРИТЬ имя службы на РЕД ОС 8)"; fi +else + skip "chronyc — не найден (ПРОВЕРИТЬ пакет chrony)" +fi + +# --- 2. Разрешено доступ для клиентских сетей (allow) --- +NETS_OK=0; NETS_TOTAL=0 +for NET in $ALLOW_NETS; do + NETS_TOTAL=$((NETS_TOTAL+1)) + if grep -qE "^allow[[:space:]]+$NET" "$CHRONY_CONF" 2>/dev/null; then + NETS_OK=$((NETS_OK+1)) + else fail "allow $NET" "нет строки в $CHRONY_CONF"; fi +done +if [[ $NETS_TOTAL -eq 0 ]]; then skip "allow-сети — не задано ALLOW_NETS" +elif [[ $NETS_OK -eq $NETS_TOTAL ]]; then ok "allow для всех $NETS_TOTAL сетей клиентов" +fi + +# --- 3. Сервер NTP слушает 123/udp --- +if root_or_skip "порт NTP (ss)"; then + if ss -uln 2>/dev/null | grep -q ":123 "; then ok "NTP слушает udp/123" + else fail "NTP порт 123" "не слушает (chronyd: allow без локального статуса?)"; fi +fi + +echo "" +echo "=== Проверить вручную ===" +echo " — chronyc clients (кто реально опрашивает)" +echo " — chronyc sources точно сообщает о вышестоящем сервере" + +echo "" +echo "=== Итог: OK=$OK FAIL=$FAIL ПРОПУЩЕНО=$SKIP ===" +[[ $FAIL -eq 0 ]] +} +main 2>&1 | tee "$LOG" +STATUS=${PIPESTATUS[0]} +echo "Лог сохранён: $LOG" +exit $STATUS