понедельник, 28 июня 2021 г.

Grafana с аутентификацией через Radius

Встала задача поднять Grafana с аутентификацией через Radius.

Сразу же была найдена статья.

Принцип работы ясен. В grafana есть специальный механизм auth.proxy, который может получать данные в виде переменных окружения. В том примере используется веб-сервер Apache, мы же воспользуемся более привычным Nginx.

Ставим grafana, nginx и libpam-radius-auth штатным для дистрибутива способом.

Настраиваем pam:

/etc/pam_radius_auth.conf
radius-server-ip:port   secret
Делаем этот файл доступным для чтения пользователю, под которым работает nginx (у меня это www-data):
chown www-data:www-data /etc/pam_radius_auth.conf
/etc/pam.d/nginx
auth    required        pam_radius_auth.so debug client_id=grafana conf=/etc/pam_radius_auth.conf
account required        pam_permit.so
session required        pam_permit.so

Настраиваем nginx:
server {
       listen 443 ssl;

       ssl_certificate /etc/ssl/cert.pem;
       ssl_certificate_key /etc/ssl/cert.key;
       ssl_protocols TLSv1.2;
       ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256;
       ssl_prefer_server_ciphers on;
       add_header Strict-Transport-Security 'max-age=604800';
       server_name grafana.example.com;

       access_log /var/log/nginx/gr.access.log;
       error_log /var/log/nginx/gr.error.log;
       location / {
           auth_pam "Auth";
           auth_pam_service_name "nginx";
           proxy_pass http://localhost:3000/;
           proxy_set_header X-WEBAUTH-USER $remote_user;
           proxy_set_header Authorization "";
       }
}

Настраиваем grafana
/etc/grafana/grafana.ini:
....
[auth.proxy]
enabled = true
....

Перезапускаем grafana-server и nginx и проверяем.

среда, 27 мая 2020 г.

Пароли в SHA256 в OpenLDAP

Понадобилось нам поднять для определенных целей OpenLDAP. С условием, что пароли, вернее хэши наших пользователей, мы будем брать из уже существующей SQL-базы. Из входящих данных у нас был SQL-запрос, вызвращающий пользователей с хэшами и утверждение нашего DBA, что пароли хешированы в SHA256.

Получаю хэш пользователя из базы, проверяю через
echo -n "test" | sha256sum
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08  -
Строка совпадает. Быстро ваяем скрипт, который заполняет нужные поля в LDAP, в том числе вставляет эту строку в качестве пароля.

Пробуем авторизоваться:
ldapwhoami -vvv -h 127.0.0.1 -p 389 -D "cn=Иванов Иван,ou=staff,dc=example,dc=com" -W
Enter LDAP Password:                                                                                             
ldap_bind: Invalid credentials (49)
Что-то не работает.

Google подтверждает, что OpenLDAP умеет в SHA256, однако разные статьи говорят, что для этого надо либо использовать сторонний модуль slapd-sha2.so, либо воспользоваться услугами самой операционной системы, ведь пароли в Linux хранятся в SHA256/SHA512.

Выбираю второй вариант. Пишут, что надо добавить префикс {CRYPT}. Чтобы указать, что это хэш sha256, делаю предположение, что надо добавить $5$:
cat ./chpass.ldif 
dn: cn=Иванов Иван,ou=staff,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {CRYPT}$5$9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

Заливаю изменение, проверяю...

ldap_bind: Invalid credentials (49)

Нахожу в OpenLDAP FAQ:
Just to state the obvious, SHA-256 and SHA-512 based "glibc" crypt algorithms $5$ and $6$ are totally different from plain (or salted) "{SHA256}" algorithms. The libc crypt variants do a lot of nonsensical transpositions to increase the computational load.

Черт, пишут что алгоритмы различаются.

Чтобы удостоверится, вставляем свой хэш из /etc/shadow в качестве пароля с префиксом {CRYPT}$6$.

Работает, конечно.

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

Параллельно в гугле находим, что идентичный команде sha256sum хэш даёт команда:
echo -n "test" | openssl dgst -sha256
(stdin)= 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Да и онлайн сервис по распознаванию хэшей подтверждает, что это действительно sha256.
Тогда как на результат команды:
openssl passwd -5
говорит Unknown.

Ладно, читаем мануалы дальше. Различие в "соли". Passwd в Linux и в openssl делают пароль с солью, а sha256sum, понятное дело, без. И как раз-таки в OpenLDAP это должно работать, при использовании префикса {SHA256}

Видимо надо искать модуль. И находим информацию, что в актуальных версиях OpenLDAP модуль уже присутствует в системе. А файл slapd-sha2.so мы не могли найти потому, что он называется по-другому. Сотни статей по openldap+sha256 уже не актуальны, кто бы мог подумать :)

Для подтверждения этого выкачиваю исходники openldap с гита, нахожу модуль и в его Makefile'е вижу сему подтверждение. Файл на выходе действительно называется pw-sha2.la / pw-sha2.so.

Пробую просто добавить префикс {SHA256}:
cat ./chpass.ldif 
dn: cn=Иванов Иван,ou=staff,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SHA256}9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

Заливаю, пробую, не работает.

Может модуль не подгружен?
Конфиг OpenLDAP сейчас хранится в самом OpenLDAP, так что смотрим:

# slapcat -b cn=config -a "(objectClass=olcModuleList)"
...
olcModuleLoad: {1}pw-sha2.la
...
И видим, что модуль загружен.

Кстати, у нас уже есть выкачанные исходники OpenLDAP. Без особой надежды лезу в них поковырятся, мож пойму, что ему надо. В readme модуля sha2 до сих пор сказано, что надо собрать slapd-sha2.so, скопировать его в нужное место и подключить через конфиг slapd.conf (т.е. инструкция в исходниках сама устарела, ведь и библиотека называется по-другому, и конфиг OpanLDAP уж много лет как в самом OpenLDAP).

Но в том же readme ниже нахожу команду для создания хэша для тестирования:
$ echo -n "secret" | openssl dgst -sha256 -binary | openssl enc -base64
K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
Что ж, мы были близки. Пароль надо завернуть в base64. И это при том, что в LDAP оно еще раз заворачивается в base64. Но не строчное его представление, а "бинарное".

Делаю base64 над своим паролем, вставляю с префиксом {SHA256}:

# echo -n "test" | openssl dgst -sha256 -binary | base64
n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=

# cat ./chpass.ldif 
dn: cn=Иванов Иван,ou=staff,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SHA256}n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=

Заливаю, проверяю, работает!

Result: Success (0)

В скрипте это можно сделать так:
echo -n "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" | xxd -r -p | base64

суббота, 2 мая 2020 г.

Обнулить все файлы в каталоге.

Для довольно специфической задачи понадобилось обнулить все файлы в каталоге:
while read line; do bash -c "> \"$line\""; done < <(ls -1)

вторник, 19 ноября 2019 г.

Apt не хочет качать по https

А вот тут был интересный кейс. Сервер со свежеобновленным Debian 10.2 не хочет качать индексные файлы из репозитория по протоколу https:
Err https://download.docker.com/linux/debian buster Release
  Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown.  Could not handshake: Error in the certificate verification. [IP: 205.251.219.17 443]
W: https://download.docker.com/linux/debian/dists/buster/InRelease: No system certificates available. Try installing ca-certificates.
W: https://download.docker.com/linux/debian/dists/buster/Release: No system certificates available. Try installing ca-certificates.
E: The repository 'https://download.docker.com/linux/debian buster Release' does not have a Release file.
E: Failed to download some files
W: Failed to fetch https://download.docker.com/linux/debian/dists/buster/Release: Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown.  Could not handshake: Error in the certificate verification. [IP: 205.251.219.17 443]
E: Some index files failed to download. They have been ignored, or old ones used instead.
Проверил ссылку из браузера -- всё ок, на той стороне сертификат валидный.
Значит дело в нашем сервере. Оно и понятно, на других серверах этот же репозиторий работает нормально.

Но ни curl, ни wget не ругается на сертификат, как и openssl s_client.

Более того, подключил еще один проверенный репозиторий по https, на него валятся такие же ошибки.

За пару часов в гугле ничего не нашел. У всех с такой ошибкой какие-то проблемы с корневыми сертификатами и им предлагают произвести стандартные танцы с бубнами вокруг пакета ca-certificates. У меня же с сертификатами всё хорошо, состав и количество совпадают с "рабочими" серверами. Но именно apt не хочет работать по https.
Дело оказалось в правах на каталог /etc/ssl/certs. Кто-то ошибочно выставил на него режим 700, поэтому curl и wget, запущенные от root добрались до корневых сертификатов, а apt из-под непривилегированного пользователя не смог.

А значит решением будет:

# chmod 755 /etc/ssl/certs/

среда, 30 октября 2019 г.

Консольная утилита для управления WordPress

У нас есть сервер, на котором крутятся сайты на WordPress для других отделов. Они их как-то сами наполняют и админят, но, конечно же, обновлять и не думают.
Nginx, PHP, Mysql я им обновлю, а как быть с самими сайтами?

Можно было бы добавить себя в админы каждого сайта, но не всё так просто. На каких-то сайтах локальная аутентификация, на других LDAP, на третьих что-то ещё.

Объединяет их то, что они лежат на одном сервере. Обновить их оказалось довольно просто (имея рутовые права на сервере).

Нужна утилита wp-cli. К сожалению, её нет в официальных репах Debian'а, но эту утилиту можно скачать с её официального сайта (это один файл на php) и положить в любой каталог из переменной path. Если мы хотим, чтобы утилита могла обновлять сама себя, её надо положить в каталог, правами на запись в который должен обладать пользователь www-data (или под кем вы там запускаете web-сервер). Ну тут смотрите сами, снижаем безопасность в угоду удобству, как обычно.

Утилите надо создать каталог с правами на запись, куда она сможет скачивать обновления Вордпресса и плагинов. Он должен лежать в домашнем каталоге пользователя web-сервера, у меня это /var/www и назвать .wp-cli.

Далее, утилиту надо запускать от имени web-сервера, это www-data в Debian по умолчанию.

Например так:

От рута:
# sudo -u www-data bash
Переходим в каталог с первым сайтом:
$ cd /var/www/site1
$ wp core check-update
$ wp core update
$ wp core updatedb
$ wp plugin update --all
Переходим в следующий и повторяем, пока не кончатся сайты. Ну а дальше скрипты для автоматизации, ansible и т.д., но вы это и без меня знаете.

среда, 27 февраля 2019 г.

Создать пользователя в DJANGO через SQL

Понадобилось попасть в админку сайта на django, имя рутовый доступ к серверу. База сайта лежала в локальном sqlite. Генерируем себе пароль с помощью утилиты djpass:
$ ./djpass ololo
Hash: pbkdf2_sha256$120000$nwEK2MXzMCj7$u3ZGMBCbdGC72pNJkh8dZ79pcYbmlGNQCrDXvvG8WuA=
Эту утилиту я поставил в мусорную тестовую виртуальную машину на Debian, дабы не засорять свой комп, а уж тем более сервер, всяким непотребством. Ставится через программу cargo, которая есть в стандартных репах Debian:
# apt install cargo
$ cargo install djpass
Если что, утилита оказывается в каталоге ~/.carbo/bin С хешем наперевес идём в базу. В моём случае, как я уже сказал, это sqlite:
# sqlite3 /path/to/db/file

sqlite> INSERT INTO "auth_user" VALUES(3,"pbkdf2_sha256$120000$nwEK2MXzMCj7$u3ZGMBCbdGC72pNJkh8dZ79pcYbmlGNQCrDXvvG8WuA=
","",1,"megaadmin","","",1,1,"2019-02-27 11:32:20","");
Готово. Далее у меня была внутреняя ошибка 500, но при включенном дебаге выяснил, что просто права к базе были некорректными, nginx не мог до неё добраться.

среда, 15 марта 2017 г.

MPLS L2VPN в OpenBSD

Тестирую виртуальный роутер Cisco XRv 9000. И оказалось, что на данный момент mpls l2vpn в них не работает.
Просто из любопытства решил посмотреть, что творится на этом фронте у других ОС, которые можно было бы взгромоздить на x86-роутер.
И оказалось, что актуальная OpenBSD умеет это "из коробки".


В этом примере сервер с OpenBSD подключен интерфейсом em0 в коммутатор ядра, где в вилане 281 ходит LDP. Рабочая машина, воткнута в порт em1, должна оказаться в VPLS-бридже (виртуальный коммутатор), находящемся на маршрутизаторе где-то в далёкой серверной и получить оттуда адрес по dhcp.
Т.е. компы со всей необъятной сети, подключенные в этот бридж, "считают", что находятся за одним обычным коммутатором.


Создаём vlan-интерфейс:
# ifconfig em0 up
# ifconfig em0 mtu 2000
# ifconfig vlan281 create
# ifconfig vlan281 vlan 281 vlandev em0
# ifconfig vlan281 up mpls
# ifconfig vlan281 10.100.15.133/30
# ifconfig vlan281 mtu 1600
Для работы LDP нужен выделенный лупбек (вообще, хорошим тоном является создание на каждом маршрутизатор лупбек-интерфейса с ip-адресом, и использование это ip-адреса в качестве router-id для разных протоколов).
# ifconfig lo1 10.100.223.220/32
Создаём pseudowire-интерфейс и бриджуем его с физическим портом.
# ifconfig mpw0 create
# ifconfig mpw0 up
# ifconfig em1 up
# ifconfig bridge0 create
# ifconfig bridge0 up
# ifconfig bridge0 add em1
# ifconfig bridge0 add mpw0
Надо добавить параметр в файл /etc/pf.conf:
set reassemble no

Теперь ospf с ядром:
router-id 10.100.223.220

area 0.0.0.0 {
   interface lo1
   interface vlan281
}
Запускаем ospfd.

И наконец ldp:
router-id 10.100.223.220

l2vpn OFFICE type vpls {
  bridge bridge0
  interface em1
  pseudowire mpw0 {
     neighbor-id 10.100.223.18
     pw-id 1111
  }
}
address-family ipv4 {
   interface vlan281
}
Запускаем ldpd. Проверяем:
# ldpctl show l2vpn pseudowires
Interface   Neighbor        PWID        Status
mpw0        10.100.223.18   1111        UP

Пробуем получать на тестовой машине dhcp.