В прошлых итерациях настраивали сервис двухфакторной авторизации, для интеграции его с 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

В браузере идем по адресу нашего сервиса, где нас встречает логин окно сервиса. Login page

Пользователя/Пароль - мы добавили на этапе создание локального пользователя.

Настройка 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: privacyidea-guide-realm.png

Отлично, теперь добавляем новый сайт резолвера. Это может быть что угодно - база данных, AD, FreeIPA. В моем случаи для теста подойдет локальная база в passwd. Добавляю резолвера: privacyidea-guide-resolvers.png

Ну и наконец, добавляем токен для пользователя: privacyidea-guide-users.png

Далее на странице отобразиться qr-коде, его нужно отсканить в мобильной приле, например - Google Authenticator. privacyidea-guide-token.png

Ну и давайте вновь постучимся на радиус, чтобы проверить как отработает авторизация:

[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"

За одно можем почекать аудит логи: privacyidea-guide-check.png

Отлично, все работает. Далее можем интегрироваться с Active Directory, Настраивать политики сервиса и подключение на Асашке.


Дополнительные ссылки