🏠: it

Перевёл программу Cobian Reflector

Cobian Reflector — преемник широко известной в узких кругах бесплатной программы для резервного копирования Cobian Backup.

Перевод занял дня четыре. Конечно, что-то переводилось вслепую и будет требовать последующего исправления, но уже сейчас перевод включён в дистрибутив и выглядит прилично. Во всяком случае, за пределы окон ничего не вылезает.

Переезд в Docker

Устройство этого сайта на сегодняшний день

Наконец-то ковыряние Докера привело к чему-то практическому. Конечно, и раньше я ставил его на работе и поднимал там всякие сервисы, но это были одиночные контейнеры и небольшая настройка. Сейчас реализована задача посложнее — переезд с моего одноплатника Orange Pi PC 2, работавшего веб-сервером без малого 4 года (сколько воды утекло с тех пор!), на неттоп, который я купил в 2016 году, завершивший свою карьеру настольного компьютера, со вставленным туда SSD Samsung 850 EVO 250 ГБ, также освободившийся от настольных задач, и смена парадигмы хостинга с монолита на микросервисы.

Технических подробностей здесь особо не будет (хотя это смешно звучит: ничего, кроме них, тут, в общем-то, и нет), потом добавлю что-то в справочник, а пока просто фиксирую по горячим следам.

На старом сервере стоял Armbian, веб-сервер Apache и база данных MySQL. Был единый каталог /var/www/html, где в корне лежал Wordpress, а в дополнительно созданных подкаталогах — другие сервисы: в /cloud — Nextcloud, в /wiki — Dokuwiki, в /mon — phpSysInfo, позже был добавлен Webtrees в одноимённую подпапку.

Не то чтобы мне нужно было позарез переезжать на новую платформу, но меня немного беспокоило, что хранилищем выступают флешки, и система стоит на карточке microSD. Хоть логи в Armbian и пишутся в память, тем не менее, ресурс флеш-носителей довольно мал — несколько месяцев назад, например, померла флешка для записи резервных копий. Ну и, конечно, хочется освоить что-то новое и быть в курсе современных прикладных направлений в ИТ. Наконец, желательно иметь более переносимую систему, которая не так привязывается к железу и в перспективе будет работать в кластере.

На неттоп, в котором памяти стало 4 ГБ после обмена с ноутбуком, была установлена Ubuntu Server 20.04 LTS с ядром HWE и Docker в качестве платформы. Затем я перенёс туда наработки, которые я делал на тестовых виртуальных машинах, и занялся миграцией данных.

Задача, главным образом, осложнялась тем, что у меня есть только одно доменное имя, и все сервисы должны работать не на поддоменах, что очень просто настраивается, а на путях после доменного имени (префиксах). Многие современные сервисы, упакованные в контейнеры, уже имеют поддержку разных режимов работы через реверс-прокси, но некоторые либо не имеют этой поддержки вовсе, либо она есть, но не работает, как в случае с Nextcloud, где можно указать параметр overwritewebroot, но работать он не будет. Из-за этого пришлось собирать Nextcloud по кускам самому. Но это даже и к лучшему, потому что официальный контейнер Nextcloud, по-хорошему, противоречит самой идее микросервисов, так как там в одном контейнере находится сразу несколько работающих процессов, что больше похоже на виртуальную машину; к тому же, при самостоятельной сборке начинаешь лучше понимать устройство системы.

Я всегда стремлюсь к экономии ресурсов, и по возможности использую либо чистый контейнер Alpine Linux (например, для php-fpm — так уж вышло), либо вариант нужного мне сервиса на базе Alpine. Иногда стремление сэкономить выходит боком — я долго возился с «лёгким» веб-сервером Lighttpd, но в случае с Webtrees не смог решить задачу «красивых ссылок» (pretty URLs) даже с помощью специального форума, и в результате решил остановиться на Nginx как самом модном и распространённом варианте на сегодняшний день, для которого везде есть куча конфигураций.

Порой я упирался в непонимание каких-то вещей, например, как раздавать права на томах, если туда смотрят 2 контейнера — nginx и php-fpm, которые работают от разных пользователей? И как раздать эти разрешения с хоста, где таких пользователей вообще нет? Заводить их там не вариант же.

Заставить работать nginx от учётки www-data у меня не вышло, но потом оказалось, что достаточно раздавать права на том с данными только для php-fpm и nginx можно вообще не трогать, а с хоста можно задавать разрешения даже для несуществующих пользователей, если просто указывать совпадающий ID:

sudo chown -R 82:82 /var/lib/docker/volumes/home_cloud/_data/cloud
# Впрочем, правильнее, наверное, так:
docker exec cloud-php chown -R www-data:www-data /var/www/html/cloud

Отдельная песня с реверс-прокси. Например, рабочий конфиг ярлыков для Nextcloud, чтобы внутри него при проверке получить зелёную галочку, оказался такой:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.nc.rule=PathPrefix(`/cloud`,`/.well-known`)"
  - "traefik.http.routers.nc.middlewares=nc-dav,nc-wellknown,nc-sts"
  - "traefik.http.middlewares.nc-dav.redirectregex.regex=(.*)/.well-known/ca(rd|l)dav"
  - "traefik.http.middlewares.nc-dav.redirectregex.replacement=$$1/cloud/remote.php/dav/"
  - "traefik.http.middlewares.nc-wellknown.replacepathregex.regex=^(/.well-known.*)"
  - "traefik.http.middlewares.nc-wellknown.replacepathregex.replacement=/cloud/index.php$$1"
  - "traefik.http.middlewares.nc-sts.headers.stspreload=true"
  - "traefik.http.middlewares.nc-sts.headers.stsseconds=31536000"

И на это уходят дни и недели. Иногда думаешь — да ну всё это к чёрту, потом опять начинаешь долбить эту стену, пока, наконец, не пробьёшся.

Помимо тех сервисов, которые у меня были, я добавил новые:

  • Photoprism — фото- и видеогалерея с распознаванием лиц, геолокацией, распознаванием дубликатов, доступом по ссылкам и т. п.
  • Bepasty — аналог Pastebin, но не только для текста. Можно выкладывать всё, что угодно.
  • Alltube — веб-морда для старого доброго youtube-dl.

Конечно, сервисы эти не то чтобы мне позарез нужны, но так как они место в квартире не занимают, пусть будут, тем более, что пригодиться они вполне могут.

Есть и убытки — не переехала страничка мониторинга, так как в контейнере она хоста не увидит, а на самом хосте поднимать ради этого веб-сервис глупо. Тандем Prometheus + Grafana — это довольно громоздко, трудоёмко и не очень-то осмысленно ради такого мелкого результата. Посмотрим позже, пока нужно хотя бы наладить какое-то резервное копирование.

Продолжение следует.

Кластеры Hyper-V, порядок в домашних каталогах, SSO для DokuWiki

Долго не мог себя заставить что-то написать, но надо, а то забывается всё.

Построил два кластера Hyper-V

Базой послужили сервера, которые освободились в результате виртуализации сервисов, которые на них крутились, занимая в среднем 10% от их мощности. Теперь появилась возможность использовать ресурсы более рационально и добавить отказоустойчивости.

Первый кластер — продуктивный на немолодых, но вполне боеспособных серверах HP Proliant 380DL Gen8. Сейчас три узла, на каждом по 192 ГБ памяти, планируется ещё два добавить в следующем году, когда для них докупят память и серверные лицензии. В качестве ОС выступает Windows Server 2019 Datacenter. Подключены полки HP P2000 и NetApp AFF-220 с флеш-массивом.

Второй — тестовый на более новых ProLiant DL380 Gen9 — их всего два, поэтому продуктив на них строить нет смысла. ОС — бесплатная Windows Hyper-V Server 2019. Подключена вторая полка HP P2000. Там крутится всё тестовое барахло, которое не нужно резервно копировать.

PS C:\> get-vm -ComputerName (Get-ClusterNode -Cluster hvc)

Name           State   CPUUsage(%) MemoryAssigned(M) Uptime             Status             Version
----           -----   ----------- ----------------- ------             ------             -------
t-docker1      Running 0           4096              5.22:48:09.8380000 Работает нормально 9.0
t-sql2017-1    Running 0           8192              5.22:48:27.3800000 Работает нормально 9.0
t-w10-1        Off     0           0                 00:00:00           Работает нормально 9.0
t-w7-2         Off     0           0                 00:00:00           Работает нормально 9.0
t-w7-3         Off     0           0                 00:00:00           Работает нормально 9.0
vmls-bpm-exch  Running 0           4096              5.22:47:09.9290000 Работает нормально 9.0
vmls-haproxy1  Off     0           0                 00:00:00           Работает нормально 9.0
vmls-jibri1    Running 0           4096              5.22:48:16.5620000 Работает нормально 9.0
vmls-jitsi1    Running 0           16384             5.22:47:28.6320000 Работает нормально 9.0
vmls-lk-test   Running 0           4096              5.22:49:02.0820000 Работает нормально 9.0
vmws-trueconf1 Running 0           8192              5.22:47:28.2950000 Работает нормально 9.0
t-w11-1        Running 0           4096              5.22:13:14.2280000 Работает нормально 9.0
vmls-jibri2    Off     0           0                 00:00:00           Работает нормально 9.0
vmls-jibri3    Off     0           0                 00:00:00           Работает нормально 9.0
vmls-jibri4    Off     0           0                 00:00:00           Работает нормально 9.0
vmls-jibri5    Off     0           0                 00:00:00           Работает нормально 9.0
vmus-wp        Running 0           2048              5.22:13:49.3510000 Работает нормально 9.0
web2-dev2      Running 0           2048              5.22:13:49.2880000 Работает нормально 9.0

Что интересно, на некоторых серверах Gen8 кэш RAID-контроллера показывался в мониторинге как сбойный, вылечилось обновлением прошивки.

Освободилась куча жёстких дисков: так как все виртуалки теперь хранятся на полках и место на нодах нужно только для операционной системы и установочных образов, я пересоздал на всех серверах локальное хранилище, сделав там RAID1 + spare, а лишние диски выдернул. Теперь запас на замену солидный.

С течением времени Hyper-V мне нравится всё больше — мало того, что можно виртуальные машины переносить между нодами даже без наличия кластера, кластеры создавать на базе бесплатного Hyper-V Server и для его функционирования не нужен никакой платный управляющий сервер, как в случае с VMware, так с 2016 версии там появилась автобалансировка нагрузки, что для компаний малого и среднего размера делает фактически ненужными инструменты типа Virtual Machine Manager. В принципе, даже без этого механизма примитивный балансировщик можно написать и самому, благо, Hyper-V прекрасно управляется через Powershell.

В следующем году, если всё будет нормально, купят ещё и устройство проброса USB-токенов по сети, тогда можно будет перенести последний бастион VMware 5.5, где живёт 1С и ему подобные вещи. Логично было бы, конечно, заняться конвертацией лицензий в электронные, но не всё возможно конвертировать, а в случае 1С имеется некое антропогенное сопротивление.

Теперь обновлять ноды кластера можно прямо посреди рабочего дня:

Suspend-ClusterNode -Name "node1" -Drain # Выгнать всех с ноды
# Далее обновлять и перезагружать ноду
Resume-ClusterNode -Name "node1" -Failback Immediate # Вернуть ноду в строй и тащить ВМ обратно

С кластеростроением связано и то, что я

Прошил SAN-свитчи

Началось с того, что после подключения к кластеру новой модной флеш-полки NetApp и перенесения туда некоторого количества виртуалок, в один прекрасный день решили обновить ноды, и после перезагрузки последней из них все виртуальные машины, лежащие на этой полке, потеряли свои жёсткие диски. Вторая полка — Хьюлет Паккард — продолжала работать как ни в чём не бывало. Началась паника, в результате после перезагрузки SAN-свитчей всё восстановилось.

Обнаружилось, что после перезагрузки кластерной ноды полка перестаёт эту ноду видеть. Дело в том, что NetApp использует виртуальный WWN, и, скорее всего, SAN-свитчи HP 8/8 с древней прошивкой v7.0.0c не вполне корректно с этим делом работают. Я предложил прошить их до максимально возможной версии, что после одобрения руководства и проделал. На своей рабочей машине я развернул FTP-сервер и прошил оба свитча в такой последовательности: v7.0.0c → v7.0.2e1 → v7.1.2b1 → v7.2.1g → v7.3.2b → v7.4.2d. Шить надо последовательно, прибавляя единицу ко второй цифре. Первую итерацию перестраховался, прошив до последней доступной мне версии в рамках одной и той же второй цифры.

Процесс обновления до Fabric OS v7.2.1

Моё предположение оказалось верным — после прошивки всё заработало как нужно, полка перестала терять хосты после их перезагрузки.

Написал скрипт контроля домашних каталогов пользователей

Два года назад я уже делал отчёт по домашним каталогам, теперь пришло время навести порядок с этим делом. Внезапно выяснилось, что групповой политики создания каталогов не было, поэтому при создании учётки и прописывании пути к каталогу он не создавался. Раньше это делали, как и всё остальное, руками, поэтому были ошибки в именах каталогов, права на папки были розданы невесть как, при выключении учётки каталог никуда не девался и продолжал валяться в общей куче, при переименовании логина пользователя каталог оставался со старым именем — в общем, бардак.

Конечно, можно было бы создать групповую политику, но она бы не учитывала всего того, что уже навертели, как и, например, смену логина, поэтому хотелось сделать что-то погибче.

После некоторых умственных борений, проб и ошибок я пришёл к такой логике: пляшем от того, что каталог может быть либо прописан, либо не прописан в учётной записи пользователя.

Если он прописан, он может:

  • Не совпадать с логином, и корректной папки не существует, но при этом есть та, которая прописана — тогда нужно переименовать текущую папку, а путь скорректировать.
  • Не совпадать с логином, и папки по прописанному пути не существует, но корректная папка существует — скорректировать путь.
  • Не совпадать с логином, но существуют и корректная папка, и неправильная — написать человеку, чтобы разобрался.
  • Не совпадать с логином, но не существует ни той папки, что прописана, ни корректной - создать и прописать правильный каталог.
  • Совпадать с логином, но каталога не существует — создать каталог.

Если домашний каталог не прописан:

  • Если есть папка, совпадающая с логином — прописать её.
  • Если папки нет — создать её и прописать в учётку.

Также, скрипт смотрит в список прав на каталоги (с помощью прекрасного модуля NTFSSecurity), и если там явно заданных (неунаследованных) прав больше единицы или в списке отсутствует логин пользователя — сбрасывает разрешения на каталог и задаёт полные права для одного пользователя. Какие разрешения были - на всякий случай сообщается человеку.

В итоге, я получаю подобные письма:

Алексеев Олег Владимирович: не был настроен диск Z, создана и прописана папка (Alekseevov).  
Анциферова Ольга Николаевна: переименована папка диска Z для соответствия с логином: Rumyanceva → antsiferovaon  
В папке Rumyanceva были выставлены неверные явные разрешения - их 4, выданы BUILTIN\Администраторы, DOMAIN\antsiferovaon  
Внукова Валентина Геннадьевна: прописанная папка диска Z (vnukovavg) не существовала и была создана.  
Горбунова Ирина Васильевна: прописанной папки диска Z не существует (Berdisheva), но существует совпадающая с логином (Gorbunova). Путь скорректирован.  
Петрова Юлия Сергеевна: прописанная папка диска Z (petrovayus) не совпадала с логином (petrovays), но так как обоих каталогов не существовало, был создан и прописан правильный.  
Фанова Ирина Анатольевна: прописанная папка диска Z (Fanovaia) не совпадает с логином (Fanova), но существуют оба каталога. Необходимо разобраться.

А тот ежемесячный отчёт двухгодичной давности я дополнил механизмом архивации каталогов отключенных или отсутствующих пользователей или удаления, если каталог пустой. Об этом теперь мне сообщается так:

Лишний каталог Abramian пуст и был удалён.
Лишний каталог Afanasieva перенесён в архив (3 файла, 0.35 МБ).
Лишний каталог Ageenko перенесён в архив (5 файлов, 0.92 МБ).
Лишний каталог Akimova пуст и был удалён.
Лишний каталог Aksenov пуст и был удалён.
Лишний каталог Alekseeva перенесён в архив (3 файла, 1.45 МБ).
Лишний каталог Alekseevmv пуст и был удалён.
Лишний каталог Alexandrov перенесён в архив (2795 файлов, 755.9 МБ).

Теперь система сама следит за порядком в домашних каталогах, красота.

Настроил единый вход (SSO) для DokuWiki

Памятуя об успехе настройки Squid и прочитав, что DokuWiki также имеет механизм работы с Active Directory и Single sign-on, решил реализовать это на практике. Ведь очень удобно, когда открываешь страницу wiki и сразу авторизуешься под своей учёткой с соответствующими правами.

Делал как и раньше в случае со Сквидом — через keytab-файл, только в этом случае пароль делал случайный, потому что нет никакого смысла задавать его извне - вводить этот пароль никуда не придётся. Перенёс keytab на сервер wiki, настроил /etc/krb5.conf. Далее нужно настраивать саму DokuWiki.

/var/www/html/conf/local.php

<?php
$conf['title'] = 'Wiki';
$conf['lang'] = 'ru';
$conf['license'] = '0';
// группа админов wiki
$conf['superuser'] = '@wiki-admins';
$conf['target']['interwiki'] = '_blank';
$conf['target']['extern'] = '_blank';
$conf['userewrite'] = '1';
$conf['useslash'] = 1;

/var/www/html/conf/local.protected.php

$conf['useacl']         = 1;
$conf['authtype'] = 'authad';
$conf['disableactions'] = 'register';

$conf['plugin']['authad']['account_suffix'] = '@domain.ru';
$conf['plugin']['authad']['base_dn'] = 'DC=domain,DC=ru';
$conf['plugin']['authad']['domain_controllers'] = 'DC1.domain.ru,DC2.domain.ru,DC3.domain.ru';
$conf['plugin']['authad']['domain'] = 'domain.ru';
$conf['plugin']['authad']['recursive_groups']   = 1;
$conf['plugin']['authad']['sso'] = 1;
// Пользователь AD wiki-admin должен входить в группу wiki-admins
$conf['plugin']['authad']['ad_username'] = 'wiki-admin';
$conf['plugin']['authad']['ad_password'] = 'P@ssw0rd';
// $conf['plugin']['authad']['debug'] = 1;

Потом Apache.

# Для начала надо установить модуль для Kerberos:
apt install libapache2-mod-auth-gssapi
# И настроить его в /etc/apache2/apache2.conf
<Directory "/var/www/html">
        AuthType GSSAPI
        AuthName "GSSAPI Wiki SSO"
        GssapiBasicAuth On
        Require valid-user
</Directory>
# Чтобы не парить людям мозги насчёт необходимости набирать полное имя
# wiki.domain.ru вместо просто wiki (это необходимо для работы SSO), делаем редирект.
# /etc/apache2/sites-available/000-default.conf
<If "%{HTTP_HOST} != 'wiki.domain.ru'">
    Redirect "/" "http://wiki.domain.ru/"
</If>

Ну, а дальше можно создавать в AD группы, включать туда пользователей и раздавать для этих групп права на соответствующие разделы и страницы.

Неожиданный апгрейд

Достался тут мне ноутбук HP 15-r062sr 2014-го года выпуска (Core i5 4210U 1700 Mhz/15.6″/1366x768/4.0Gb/500Gb/DVD-RW/Intel HD Graphics 4400/Wi-Fi/Bluetooth) в довольно мизерабельном состоянии — полуразобранным он хранился в квартире не в лучших условиях несколько лет. Винтики прилагались в пакетике. Аппарат включался, но операционка не грузилась, и постоянно при включении выдавалась ошибка контрольной суммы BIOS.

Внешний вид ноутбука. Картинка из интернета: у меня, к сожалению, снимать не было времени.

Эта модель ноутбука не отличается удобством в разборке — нижняя крышка тут сплошная и не имеет отсеков доступа к памяти и жёсткому диску, поэтому нужно разбирать его целиком — выкручивать винтики нижней крышки, снимать угловые пластмасски под экраном — там винтики под клеящимися ножками, снимать клавиатуру, выкручивать винтики под ней (до этого момента уже было разобрано), отключать шлейфы кнопки питания и тачпада, потом выщёлкивать верхнюю крышку, выкручивать жёсткий диск, и только потом демонтировать материнскую плату, под которой прячутся два разъёма памяти и батарейка CMOS.

Нижняя часть

Батарейка вздулась и заржавела, задев своими потёками соседние детали и корпус, также с мясом были выдраны несколько стоек для винтов. Так как железные сердечники стоек сохранились, перекатываясь внутри корпуса, я восстановил их известным способом «суперклей + сода», а батарейку заменил на новую, предварительно очистив посадочное место от окислов. Конечно, я основательно очистил всё остальное — пылесос, кисточка для смахивания пыли, жижа для оргтехники, спирт, тряпочки и т. п., так что аппарат стал выглядеть прилично.

Теперь нужно было выяснить, почему не грузится система и вообще, что с жёстким диском. Я изготовил загрузочную флешку с Xubuntu, полез в BIOS и включил поддержку Legacy boot. При перезагрузке я замешкался, и неожиданно начала загружаться Windows 7. Стало всё понятно — изначально системой на этом ноутбуке была Windows 8, которая грузилась по Secure boot, затем установили Windows 7 и настроили BIOS на старый загрузчик, а батарейка сдохла, BIOS сбрасывался по умолчанию и «семёрка» уже не грузится, т. к. Secure boot она не понимает.

Так как память в этом ноутбуке того же типа, что и в неттопе, который я собирал 5 лет назад, а процессор тут гораздо мощнее, я решил переехать с неттопа на этот ноутбук. Поэтому я поставил в ноутбук планку в 8 ГБ и твердотельник из неттопа, а планку в 4 ГБ и обычный шпиндельный 500-гигабайтный жёсткий диск Toshiba — в обратном направлении. На неттоп я поставил ту самую Xubuntu с флешки с целью возможной последующей продажи вместе с монитором.

В результате получился неплохой довольно шустренький ноутбук как апгрейд неттопа без каких-либо материальных затрат (300 рублей за батарейку и суперклей не в счёт). Аккумулятор у ноутбука, правда, убитый, но это несущественно, можно и новый купить, если что (740715-001).

Что сделал - 10

Продолжаем бахвалиться, юбилейный выпуск. Сегодня в программе сплошное построение велосипедов, что логично — скоро открытие велосезона.

Авторесет виртуальной машины при недоступности HTTP или если она не отвечает на пинг

Есть виртуальная машина на Ubuntu 8.04, перевезённая мной на Hyper-V с железки несколько месяцев назад, где крутится веб-сервис, управляемый CMS отечественного производства RBC Contents 4.0. В каталоге веб-сервера находится более миллиона файлов. Операционная система старая, несовместимая с виртуальной средой, поэтому сетевые адаптеры там пришлось ставить не современные синтетические, а старые эмулируемые (100 Мбит). Мало того, что версия системы управления контентом античных времён — она уже больше 10 лет вообще не существует в природе, как и компания, её выпускавшая. Инструкций тоже нет, в интернете нашлись два документа по три странички, писанных на коленке и совершенно бесполезных. В общем, классический «чёрный ящик», который невозможно тронуть, чтобы он, чего доброго, не развалился, но, вместе с тем, необходимо поддерживать его работоспособность.

Ящик время от времени по неизвестным причинам либо перестаёт отвечать по сети, либо вешается намертво; особенно радует, когда он это делает в три часа ночи. В журналах пусто. Так как всегда решением проблемы является нажатие кнопки сброса, я написал скрипт, который в нерабочее время каждые 10 минут проверяет доступность ящика по сети и порта HTTP. Если что-то не отвечает, скрипт ищет машину в кластере и жмёт ей на ресет, после чего пишет мне письмо, почему он это сделал.

$name = "webserver"
$ip = "192.168.1.10"

if (!(Test-Connection $ip -Count 4 -Quiet -OutVariable ping) -or `
!(Test-NetConnection $ip -Port 80 -OutVariable http).TcpTestSucceeded) {
$vm = Get-Clustergroup |? {$_.grouptype -eq 'VirtualMachine' -and $_.name -eq "$name"} |get-vm

  if ($vm -and $vm.State -eq "Running") {

  $vm |Restart-VM -force

  $body = "<p>Причины:</p>"
  $body += "<ul>"
    if (!$ping) {$body += "<li>Нет сетевого соединения</li>"}
    if (!$http.TcpTestSucceeded) {$body += "<li>Нет ответа по HTTP</li>"}
  $body += "</ul>"

  Send-MailMessage -SmtpServer mail.domain.ru -From support@domain.ru -Subject "Hyper-V - сервер $name был принудительно перезагружен" `
  -To admin@domain.ru -Body $body -BodyAsHtml -Encoding utf8
  }
}

Всё же, виртуализация в любом случае имеет преимущества, потому что ящик примерно так же вис и в свою бытность на железке, а до кнопки ресета там просто так дотянуться было нельзя.

Нужно, конечно, сделать поизящнее — привязать срабатывание скрипта к Zabbix, это дело ближайшего будущего.

Группы рассылки на базе групп подразделений компании

Обратились в просьбой сделать группу рассылки на один из отделов компании. Чтобы не возвращаться больше к этой теме в будущем, решили сделать такие группы сразу для всех отделов (кроме руководства, конечно).

Сначала я сделал скриптом динамические группы рассылки, т. е., в рассылку входят члены группы того или иного отдела. Но выяснилось, что так не работает, потому что структура отделов иерархическая, а динамическая группа рассылки не умеет смотреть в группу домена рекурсивно. Ведь тот или иной сотрудник входит в несколько разных вложенных друг в друга отделов, и должен входить во все группы рассылки этих отделов.

Пришлось создать обычные группы рассылки, а членство в группах спрашивать у домена.

function Get-ADGroupMemberEnabledAndMail {
param(
[parameter(mandatory=$true)]
$group
)
Get-ADGroupMember "$group" -Recursive |? objectclass -eq 'user' |% {
    Get-ADUser -filter "name -eq '$($_.name)' -and enabled -eq 'True'" -Properties mail
    }
}

В результате написал скрипт, где группы рассылки автоматически создаются и удаляются в зависимости от наличия групп подразделений компании, а пользователи добавляются и удаляются из групп рассылки в зависимости от их членства в группах подразделений.

По результатам работы скрипт шлёт отчёт, причём, я распробовал всякие html-символы, чтобы сделать его более читаемым и лаконичным. Примерный вид:

Отдел по развитию (группа рассылки)
Управление по повышению (группа рассылки)
Бумажкин Иван Ильич Дирекция по улучшению (группа рассылки)
Бюрократов Тихон Тарасович Группа по превозмоганию (группа рассылки)

Всё отлично работает, но есть одна мысль — ведь можно вместо довольно большого количества тяжёлых запросов к контроллерам домена брать подразделения, к которым принадлежит пользователь, просто из выгрузки штатного расписания, которую уже давно приводит в порядок мой парсер, написанный полтора года назад. Да, всё равно нужно будет получать дополнительную информацию о пользователе из домена, но хотя бы не придётся рекурсивно лопатить десятки групп. С другой стороны, мы имеем дело с реальным положением вещей, которые были приведены в соответствие с выгрузкой ранее. В общем, есть над чем подумать.

Обнаружение лишних объектов в корне DFS

Удивительным образом — видимо, не до конца разобрались в своё время в хитросплетениях раздачи прав в DFS — в корень списка папок на распределённых файловых ресурсах каким-то образом попадают пользовательские ярлыки, файлы и даже иногда каталоги. Это бывает нечасто, но тем не менее, приятнее от этого не становится, а пытаться кардинально решить эту проблему, экспериментируя с перенастройкой прав на работающей системе — это рискованная авантюра, так что опять будет паллиатив.

Удалить этот скапливающийся хлам вручную бывает непросто — нужно искать, на каком конкретно сервере он лежит и удалять уже оттуда, потому что если админ подключен к DFS на одном сервере, а хлам лежит на другом, то через DFS админ удалить хлам не сможет, даже имея все полномочия — система пишет, что файлы не найдены. Ещё нюанс — из команд Powershell, относящихся к DFS, я не смог получить путей к его корням на локальных серверах, т. е., элегантно извлечь данные из одного источника не вышло. Пришлось просто перечислить все локальные пути в явном виде в скрипте, благо, их немного.

А как вообще отделить хлам от легитимных папок? Оказывается, папки в DFS имеют атрибут d----l (reparse point), то есть, это даже и не папки, а ссылки. Поэтому, вычислить хлам можно так:

dir `
"\\server1\c$\DFS_roots\*\*",
"\\server2\c$\корни_DFS\*\*",
"\\server3\c$\DFS_roots\*\*" |
? mode -ne 'd----l'

Скрипт, конечно, данные сам не удаляет (мало ли что может туда попасть?), а шлёт письмо, где перечислены потенциально лишние объекты, обёрнутые в команды для их удаления.

Автодобавление разрешения на почтовые ящики для группы

Это нужно, чтобы группе определённых сотрудников иметь возможность заходить через почтовый веб-интерфейс на другой ящик, вместо того, чтобы каждый раз подключать его руками и тянуть все эти гигабайты добра на свой комп.

Как обычно, хотелось дать разрешения на уровне организации Exchange, чтобы сделать это один раз и больше к теме не возвращаться. Вместе с тем, не хотелось и давать слишком много привилегий этой группе — разрешений по управлению почтовой системой ей не требовалось. Кроме того, были мысли дать права только на чтение.

В результате поиска я пришёл к выводу, что ни первого, ни второго сделать не удастся — привилегий будет слишком много, если давать их выше ящика, а доступ на чтение для веб-интерфейса невозможен. Допускаю, что решение есть, но какое-то уж слишком замороченное, да и в моём случае это было непринципиально.

Не стал писать нового скрипта, дополнил старые — в один, который контролирует видимость в глобальной адресной книге, добавил сам функционал раздачи прав на ящики, где они ещё не были розданы, а сводный отчёт по Exchange дополнил данными по явно заданным разрешениям на ящики, раз уж всё равно ковырял эту тему.

$accessNotGranted = $allUserMbxes |? {!((Get-MailboxPermission $_).user -match "$fullControlGroup")}
if ($accessNotGranted) {
    $accessNotGranted |
    Add-MailboxPermission -User "$fullControlGroup" -AccessRights FullAccess -InheritanceType All
}