В прошлых итерациях настраивали сервис двухфакторной авторизации, для интеграции его с Cisco ISE. На этот раз решил попробовать проинтегрировать аналогичную LinOTP прилу - PrivacyIdea.
На самом деле PrivacyIdea это форк LinOTP, который активно развивается разрабами и имеет более симпотичный WebUI. Да и стоит отметить, что некоторые фичи уже добавленые в приложение из коробки. И не нужно реализовывать костели, которые я делал ранее. Стоит отметить, что стабильная версия LinOTP работает на втором python2, что на сегодня уже считаеться немного легаси =). Я пробовал собирать приложение на python3, но из-за различных проблем в процессе использования сервиса, у меня просто опустились руки.
Итак, перейдем к установке. Ставить будем на AlmaLinux8.7, в этот раз развернем в standalone на хосте. Далее я планирую развернуть Active/Passive схему с мульти мастерами на бекендах, но пока что есть сомненися относительно mysql в master-to-master. Буду тестировать.
Установка Mariadb
Установим и проинициализируем базу данных под сервис.
[root@2fa-srv01 ~]# yum install mariadb-server mariadb mariadb-devel -y
Запускаем сервис бд, и инициализаруем инстанс:
[root@2fa-srv01 ~]# systemctl enable --now mariadb
[root@2fa-srv01 ~]# mysql_secure_installation
Подключаемся к базе, создаем базу и пользователя:
[root@2fa-srv01 ~]# mysql -u root -p
---
# Создаем новую базу
MariaDB [(none)]> create database pi_db;
# Создаем пользователя с правом логина локально
MariaDB [(none)]> create user 'pi_user'@'localhost' identified by 'password';
# Даем пользователю полные права
MariaDB [(none)]> grant all privileges on pi_db.* to 'pi_user'@'localhost';
Установка PrivacyIdea
Для начала создаем каталоги, под нужны сервиса:
[root@2fa-srv01 ~]# mkdir /etc/privacyidea /opt/privacyidea /var/log/privacyidea
Добавляем системного пользователя:
[root@2fa-srv01 ~]# useradd -r -M -U -d /opt/privacyidea privacyidea
Ну сразу же меняем владельца на ранее созданных каталогах:
[root@2fa-srv01 ~]# chown privacyidea:privacyidea /opt/privacyidea /etc/privacyidea /var/log/privacyidea
Ставим зависимости для работы с пакетыми и сборкой:
[root@2fa-srv01 ~]# yum install python3 python3-virtualenv python3-wheel git openssl-devel swig openldap-devel libsodium gcc
(Для установки пакета libsodium
, нужно предварительно установить - epel репозиторий.)
Последующие действия будем выполнять из под системного пользователя - privacyidea
, поэтому переключаемся на него.
[root@2fa-srv01 ~]# su - privacyidea
[privacyidea@2fa-srv01 ~]$
В документации по инсталяции рекомендуется установка пакетов в виртуальное окружение. Создаем окружение и переключаемся в него:
[privacyidea@2fa-srv01 ~]$ virtualenv /opt/privacyidea
[privacyidea@2fa-srv01 ~]$ . /opt/privacyidea/bin/activate
Устанавливаем прилу. В переменные окружения добавил переменную с версией приложения. На момент написания заметки ластецкая версия - 3.8.1
, поэтому ставим ее.
(privacyidea) [privacyidea@2fa-srv01 ~]$ export PI_VERSION=3.8.1
Через pip устанавливаем зависимости самого приложения:
(privacyidea) [privacyidea@2fa-srv01 ~]$ pip install -r https://raw.githubusercontent.com/privacyidea/privacyidea/v${PI_VERSION}/requirements.txt
Из под питоновского пакетного менеджера ставим сам сервис:
(privacyidea) [privacyidea@2fa-srv01 ~]$ pip install privacyidea==${PI_VERSION}
Если прила успешно установлена, создаем новый конфигурационный файл для сервиса:
(privacyidea) [privacyidea@2fa-srv01 ~]$ vi /etc/privacyidea/pi.cfg
Сам файл конфигурации, из основных настроек, нам нужно поменять строку подключения к базе:
import logging
# The realm, where users are allowed to login as administrators
SUPERUSER_REALM = ['super']
# Your database
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://pi_user:pwdpwd@localhost/pi_db'
# This is used to encrypt the auth_token
#SECRET_KEY = 't0p s3cr3t'
# This is used to encrypt the admin passwords
#PI_PEPPER = "Never know..."
# This is used to encrypt the token data and token passwords
PI_ENCFILE = '/etc/privacyidea/enckey'
# This is used to sign the audit log
PI_AUDIT_KEY_PRIVATE = '/etc/privacyidea/private.pem'
PI_AUDIT_KEY_PUBLIC = '/etc/privacyidea/public.pem'
PI_AUDIT_SQL_TRUNCATE = True
# The Class for managing the SQL connection pool
PI_ENGINE_REGISTRY_CLASS = "shared"
PI_AUDIT_POOL_SIZE = 20
PI_LOGFILE = '/var/log/privacyidea/privacyidea.log'
PI_LOGLEVEL = logging.INFO
Сервис использует механизм шифрования внутренних админских паролей, что бы это работало нужно в значение переменной PI_PEPPER
(в конфиге /etc/privacyidea/pi.cfg
), поместить набор рандомных символов:
(privacyidea) [privacyidea@2fa-srv01 ~]$ PEPPER="$(tr -dc A-Za-z0-9_ </dev/urandom | head -c24)"
(privacyidea) [privacyidea@2fa-srv01 ~]$ echo "PI_PEPPER = '$PEPPER'" >> /etc/privacyidea/pi.cfg
Аналогично прописываем значение для переменной - SECRET_KEY
, значением этого параметра будут зашифровываться наши токены.
(privacyidea) [privacyidea@2fa-srv01 ~]$ SECRET="$(tr -dc A-Za-z0-9_ </dev/urandom | head -c24)"
(privacyidea) [privacyidea@2fa-srv01 ~]$ echo "SECRET_KEY = '$SECRET'" >> /etc/privacyidea/pi.cfg
Теперь при помощи утилиты pi-manage
, конфигурим ключи и портируем схемы в базу.
Генерим ключ шифрования для бд:
(privacyidea) [privacyidea@2fa-srv01 ~]$ pi-manage create_enckey
Генерим ключ для верификации лог-записей:
(privacyidea) [privacyidea@2fa-srv01 ~]$ pi-manage create_audit_keys
Создаем структуру для нашей базы:
(privacyidea) [privacyidea@2fa-srv01 ~]$ pi-manage createdb
(privacyidea) [privacyidea@2fa-srv01 ~]$ pi-manage db stamp head -d /opt/privacyidea/lib/privacyidea/migrations/
Добавляем локального админа, для доступа к WebUI админке:
(privacyidea) [privacyidea@2fa-srv01 ~]$ pi-manage admin add admin
Настройка Apache
Для взаимодействия с сервисом установим и настроим вебсервер. Выходим из окружения и ставим вебсервер и модули к нему:
[root@2fa-srv01 ~]# yum install -y httpd httpd-devel mod_ssl redhat-rpm-config
Вновь переключаемся на пользователя privacyidea
, и проваливаемся в ранее созданное окружение для того, чтобы поставить wsgi-модуль.
[root@2fa-srv01 ~]# su - privacyidea
[privacyidea@2fa-srv01 ~]$ . /opt/privacyidea/bin/activate
Из под пользователя в окружении ставим модуль - wsgi.
(privacyidea) [privacyidea@2fa-srv01 ~]$ pip install mod_wsgi
Отлично, теперь в каталог с конфигами для апача кладем конфигу для нашего веб сервера, которую скачаем:
(privacyidea) [privacyidea@2fa-srv01 ~]$ exit
[root@2fa-srv01 ~]# cd /etc/httpd/conf.d/
[root@2fa-srv01 conf.d]# curl -o privacyidea.conf https://raw.githubusercontent.com/NetKnights-GmbH/centos7/master/SOURCES/privacyidea.conf
В принципе в конфиге можно больше нечего не менять, уже из коробки апач будет работать.
Только нужно дефолтные конфиги удалить:
[root@2fa-srv01 conf.d]# rm -rf welcome.conf ssl.conf
Теперь нужно добавить wsgi модуль в загрузку апача. Для этого создаем линк на установленный модуль в окружении:
[root@2fa-srv01 ~]# ln -s /opt/privacyidea/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so /etc/httpd/modules/
И подключаем модуль:
[root@2fa-srv01 ~]# echo "LoadModule wsgi_module modules/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so " >> /etc/httpd/conf.modules.d/99-wsgi.conf
Для проверки сервиса, сгенерим временные самоподписные сертификат и ключ:
[root@2fa-srv01 ~]# openssl req -subj '/CN=192.168.10.44' -new -newkey rsa:2048 -sha256 -days 3650 -nodes -x509 -keyout /etc/pki/tls/private/localhost.key -out /etc/pki/tls/certs/localhost.crt
Для общего доступа к файлам privacyidea, я добавил пользователя apache в группу privacyidea:
[root@2fa-srv01 ~]# usermod -aG privacyidea apache
Не забываем, открыть порты на фаерволе:
[root@2fa-srv01 ~]# firewall-cmd --add-port={80,443}/tcp --permanent
[root@2fa-srv01 ~]# firewall-cmd --reload
Ну и на последок качаем wsgi-скриптик для работы сервиса:
[root@2fa-srv01 ~]# cd /etc/privacyidea/
[root@2fa-srv01 privacyidea]# curl -O https://raw.githubusercontent.com/NetKnights-GmbH/centos7/master/SOURCES/privacyideaapp.wsgi
Бывало так, что я продолбал с правами на файлы, поэтому еще раз проверяю и меняю владельца/группу в каталогах сервиса.
[root@2fa-srv01 privacyidea]# chown -R privacyidea:privacyidea /opt/privacyidea/ /etc/privacyidea/
Ну и запускаем сервис,
[root@2fa-srv01 conf.d]# systemctl enable --now httpd
В браузере идем по адресу нашего сервиса, где нас встречает логин окно сервиса.
Пользователя/Пароль - мы добавили на этапе создание локального пользователя.
Настройка Radius
В данной инсталяции радиус нужен для подключения Cisco Asa в качестве клиента, на которой в свою очередь разруливается Remove VPN. В эко-системе PrivacyIdea связь с сервисом реализована через FreeRadius Plugin, который представляет из себя обычный перловый модуль. Для работы плагина нужно установить перловые зависимости:
# Включаем репозиторий - PowerTools
[root@2fa-srv01 privacyidea]# yum config-manager --set-enable powertools
# Ставим зависимости
[root@2fa-srv01 privacyidea]# yum install freeradius perl freeradius-perl perl-Config-IniFiles perl-Try-Tiny perl-LWP-Protocol-https perl-JSON perl-Unicode-String perl-URI-Encode -y
Конфигурацию radius-сервера начнем с указания способа авторизации, который прописаеться в файле - users
:
[root@2fa-srv01 privacyidea]# mv /etc/raddb/users /etc/raddb/users.df
[root@2fa-srv01 privacyidea]# echo "DEFAULT Auth-Type := perl" >> /etc/raddb/users
Как я упоминал ранее клиентом будет выступать асашка, поэтому добавляем под нее контекст в файл - clients
:
[root@2fa-srv01 privacyidea]# mv /etc/raddb/clients.conf /etc/raddb/clients.conf.df
[root@2fa-srv01 privacyidea]# cat /etc/raddb/clients.conf
---
client ASA5500 {
ipaddr = 192.168.110.20 # Active ISE node
netmask = 32
secret = 'PASSWORD' #shared secret
}
client 127.0.0.1/32 {
shortname = local
secret = 'pwdpwd'
}
Второго клиента я добавил для того, что бы протестировать работу radius-сервера.
С гитхаб репозиторая качаем Radius плагин:
[root@2fa-srv01 privacyidea]# curl -O https://raw.githubusercontent.com/privacyidea/FreeRADIUS/master/privacyidea_radius.pm
Модуль который стянули, нужно скопировать или линкануть в каталог freeradius:
[root@2fa-srv01 privacyidea]# ln -s /opt/privacyidea/privacyidea_radius.pm /etc/raddb/mods-config/perl/
Редактируем модуль перла в конфигурации radius, где пропишем путь до нашего плагина:
[root@2fa-srv01 privacyidea]# vim /etc/raddb/mods-available/perl
---
perl {
filename = ${modconfdir}/${.:instance}/privacyidea_radius.pm
}
И далее подключаем модуль,
[root@2fa-srv01 privacyidea]# ln -s /etc/raddb/mods-available/perl /etc/raddb/mods-enabled/
Теперь нужно создать конфигурацию для radius-сайта:
[root@2fa-srv01 privacyidea]# vi /etc/raddb/sites-available/privacyidea
---
server default {
listen {
type = auth
ipaddr = *
port = 0
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
listen {
ipaddr = *
port = 0
type = acct
limit {
}
}
authorize {
preprocess
digest
suffix
ntdomain
files
expiration
logintime
pap
update control {
Auth-Type := Perl
}
}
authenticate {
Auth-Type Perl {
perl
}
digest
}
preacct {
suffix
files
}
accounting {
detail
}
session {
}
post-auth {
}
pre-proxy {
}
post-proxy {
}
}
Подключаем сайт:
[root@2fa-srv01 privacyidea]# ln -s /etc/raddb/sites-available/privacyidea /etc/raddb/sites-enabled/
# Отключаем дефолтные конфиги
[root@2fa-srv01 privacyidea]# rm /etc/raddb/sites-enabled/{default,inner-tunnel,eap}
Модуль будет обращаться на REST API основного сервиса, для этого нам нужно создать конфиг для модуля:
[root@2fa-srv01 privacyidea]# vi /etc/privacyidea/rlm_perl.ini
---
[Default]
URL = https://127.0.0.1/validate/check
REALM = localrealm
#RESCONF = flat_file
Debug = True
SSL_CHECK = False
На этом с радиусом закончили, открываем порты для доступа к сераверу и запускаем сервис:
[root@2fa-srv01 privacyidea]# firewall-cmd --add-port={1812,1645}/udp --permanent
[root@2fa-srv01 privacyidea]# firewall-cmd --reload
Запускаем сервис:
[root@2fa-srv01 privacyidea]# systemctl enable --now radiusd
Тестирование Radius
Протестируем корректность работы радиус сервера. Затестить можно отправив локальный запрос с самого сервера. Для реализации этой задачи потребуется установить утилиту:
[root@2fa-srv01 privacyidea]# yum install freeradius-utils
Теперь кидаем запрос на радиус:
[root@privacyidea-srv01 privacyidea]# echo "User-Name=user, User-Password=password" | radclient -sx localhost auth pwdpwd
---
Sent Access-Request Id 210 from 0.0.0.0:38342 to 127.0.0.1:1812 length 44
User-Name = "tony"
User-Password = "1122158481"
Cleartext-Password = "1122158481"
Received Access-Reject Id 210 from 127.0.0.1:1812 to 127.0.0.1:38342 length 62
Reply-Message = "wrong otp value. previous otp used again"
(0) -: Expected Access-Accept got Access-Reject
Как видно из вывода авторизация проваливается. Оно и очевидно, я попытался авторизоваться из под несуществуюшего пользователя.
Создадим пользователя и повторим попытку. Для этого подключаемся к WebUI консольки сервиса.
Так как это свежая инсталяция у меня нечего не настроено. Поэтому добавляем новый Realm
:
Отлично, теперь добавляем новый сайт резолвера. Это может быть что угодно - база данных, AD, FreeIPA. В моем случаи для теста подойдет локальная база в passwd
. Добавляю резолвера:
Ну и наконец, добавляем токен для пользователя:
Далее на странице отобразиться qr-коде, его нужно отсканить в мобильной приле, например - Google Authenticator.
Ну и давайте вновь постучимся на радиус, чтобы проверить как отработает авторизация:
[root@privacyidea-srv01 privacyidea]# echo "User-Name=tony, User-Password=1122158481" | radclient -sx localhost auth pwdpwd
---
Sent Access-Request Id 73 from 0.0.0.0:48756 to 127.0.0.1:1812 length 44
User-Name = "tony"
User-Password = "1122158481"
Cleartext-Password = "1122158481"
Received Access-Accept Id 73 from 127.0.0.1:1812 to 127.0.0.1:48756 length 48
Reply-Message = "privacyIDEA access granted"
За одно можем почекать аудит логи:
Отлично, все работает. Далее можем интегрироваться с Active Directory, Настраивать политики сервиса и подключение на Асашке.