#!/bin/bash
# Помощник для операций со временем, которые требуют root: пояс, ручное время,
# синхронизация с внешними NTP.
#
# ПОЧЕМУ ОТДЕЛЬНЫЙ СКРИПТ, а не права службе. Дать процессу CAP_SYS_TIME или
# пустить его в sudo с шаблоном `timedatectl *` — значит открыть весь
# timedatectl, а через него и произвольные аргументы. Здесь список команд
# закрытый, каждый аргумент проверяется, и в sudoers разрешён РОВНО этот файл
# без подстановок.
#
# Вызывается как:  sudo /opt/spektr/bin/spektr-time <команда> [аргумент]
set -euo pipefail

die() { echo "$1" >&2; exit 1; }

case "${1:-}" in

  timezone)
    zone="${2:-}"
    # только из списка самой системы — никакой записи произвольных путей
    timedatectl list-timezones | grep -qxF "$zone" || die "неизвестный часовой пояс"
    timedatectl set-timezone "$zone"
    ;;

  settime)
    # строго ГГГГ-ММ-ДД ЧЧ:ММ:СС, иначе не пропускаем
    stamp="${2:-}"
    [[ "$stamp" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}$ ]] \
      || die "время задаётся как ГГГГ-ММ-ДД ЧЧ:ММ:СС"
    # при активной синхронизации systemd менять время запрещает — гасим её:
    # ручная установка и внешняя синхронизация взаимоисключающи по смыслу
    timedatectl set-ntp false
    timedatectl set-time "$stamp"
    ;;

  sync)
    case "${2:-}" in
      on)  timedatectl set-ntp true ;;
      off) timedatectl set-ntp false ;;
      *)   die "sync on|off" ;;
    esac
    ;;

  servers)
    # список через запятую; допускаем только имена хостов и IPv4
    list="${2:-}"
    [[ "$list" =~ ^[A-Za-z0-9.,:_-]*$ ]] || die "недопустимые символы в списке серверов"
    conf=/etc/systemd/timesyncd.conf.d/spektr.conf
    mkdir -p "$(dirname "$conf")"
    if [ -z "$list" ]; then
      rm -f "$conf"                       # пусто — вернуть системные значения
    else
      printf '# создано СПЕКТРом\n[Time]\nNTP=%s\n' "${list//,/ }" > "$conf"
    fi
    systemctl restart systemd-timesyncd 2>/dev/null || true
    ;;

  show)
    # то, что нужно интерфейсу, одним вызовом
    timedatectl show -p Timezone -p NTP -p NTPSynchronized -p TimeUSec
    timedatectl show-timesync -p ServerName -p ServerAddress 2>/dev/null || true
    ;;

  zones)
    timedatectl list-timezones
    ;;

  *)
    die "команды: timezone <зона> | settime <ГГГГ-ММ-ДД ЧЧ:ММ:СС> | sync on|off | servers <список> | show | zones"
    ;;
esac
