OpenStack Keystone

Раньше был отдельным системным сервисом, но с выходом Newton уехал в http, как uwsgi приложение, однако от этого менее удобным быть не перестал.

Система служит как основная система для авторизации пользователей, а так же всевозможные ACL уже внутри OpenStack.

Установка

Хочу заметить, что мы будем ставить релиз Rocky, который не вот прям самый последний, а вполне уже пообкатанный. Настраиваем репозитории и в путь1)

# yum install openstack-keystone httpd mod_wsgi

Настройка

Базовых крутилки в принципе две, остальное на любителя:

/etc/keystone/keystone.conf
[database]
connection = postgresql://openstack:DBPASS@mgt1.cloud.ow1.in/keystone
 
[token]
provider = fernet

Хочу заметить, что мы отступили от официальной документации, которая пропагандирует Mariadb и взяли postgres, поэтому строка подключения к БД поменялась.

Собственно теперь остаётся смигрировать схему БД:

# su -s /bin/sh -c "keystone-manage db_sync" keystone

Если всё хорошо, то в /var/log/keystone/keystone.log будет написано, что база успешно смигрировалась.

Инициализируем Fernet ключи

# keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
# keystone-manage credential_setup --keystone-user keystone --keystone-group keystone

И наконец инициализируем наш первый сервис в регистри:

# keystone-manage bootstrap --bootstrap-password ADMIN_PASS \
  --bootstrap-admin-url http://mgt1.cloud.ow1.in:5000/v3/ \
  --bootstrap-internal-url http://mgt1.cloud.ow1.in:5000/v3/ \
  --bootstrap-public-url http://mgt1.cloud.ow1.in:5000/v3/ \
  --bootstrap-region-id RegionOne

UWSGI

В очередной раз отойдём от официальной документации и окунёмся в мир альтернативных решений, а именно - вместо использования Apache2) мы будем использовать связку uwsgi + nginx3)

Итак, сетапим нужное:

# yum install nginx uwsgi uwsgi-plugin-python

Кстати последний пакет очень важен, на поиск того, что он нужен я потратил минут 20. Ну и корячим конфиги соответственно:

/etc/uwsgi.d/keystone-public.ini
[uwsgi]
wsgi-file = /usr/bin/keystone-wsgi-public
processes = 4
uid = keystone
thunder-lock = True
lazy-apps = True
name = keystone-public
gid = keystone
master = True
plugins = python
buffer-size = 65535
enable-threads = True
socket = 127.0.0.1:5001
keystone-admin.ini
[uwsgi]
wsgi-file = /usr/bin/keystone-wsgi-admin
processes = 4
uid = keystone
thunder-lock = True
lazy-apps = True
name = keystone-admin
gid = keystone
master = True
plugins = python
buffer-size = 65535
enable-threads = True
socket = 127.0.0.1:35358

Ну и конфиг nginx

/etc/nginx/conf.d/keystone.conf
server {
    listen      5000;
    server_name mgt1.cloud.ow1.in ext-mgt1.cloud.ow1.in;
    charset     utf-8;
 
    location / {
        uwsgi_pass  127.0.0.1:5001;
        include     /etc/nginx/uwsgi_params;
    }
}
 
server {
    listen      35357;
    server_name mgt1.cloud.ow1.in ext-mgt1.cloud.ow1.in;
    charset     utf-8;
 
    location / {
        uwsgi_pass  127.0.0.1:35358;
        include     /etc/nginx/uwsgi_params;
    }
}

А теперь мякотка про uWSGI - в centos 7 данная поделка запускается с дропнутыми привилегиями на uwsgi:uwsgi, соответственно дроп привелегий для других скриптов, запускаемых радительским инстансом, возможен только в рамках тех групп, которые доступны uwsgi. Я решил вопрос топорно - заюзал возможности systemd:

/etc/systemd/system/uwsgi@.service
[Unit]
Description=uWSGI Emperor Service for %i
After=syslog.target
 
[Service]
EnvironmentFile=-/etc/sysconfig/uwsgi
ExecStart=/usr/sbin/uwsgi --ini /etc/uwsgi.d/%i.ini
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT
Restart=always
Type=notify
StandardError=syslog
NotifyAccess=all
 
[Install]
WantedBy=multi-user.target

А сам сервис uwsgi выключил (и выкинул файл /etc/uwsgi.ini от греха)

Удобство

Дабы не писать каждый раз кучу аргументов для openstack client я, как и документация, предлагаю использовать файлик с экспортами. В прицнипе тут вопрос личного секьюрити, как его хранить и подключать. Я же просто положу его в /etc/creds и буду делать source при входу на сервер

/etc/creds
export OS_USERNAME=admin
export OS_PASSWORD=ADMIN_PASS
export OS_PROJECT_NAME=admin
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_AUTH_URL=http://mgt1.cloud.ow1.in:5000/v3
export OS_IDENTITY_API_VERSION=3

Настройка keystone

Теперь начинается самое интересное действо. Мы начинаем сопрягать запчасти самого OpenStack. В мире данного оркестратора базовым элементом в иерархии запчастей является домен. По умолчанию в принципе есть уже default и им бы можно было удовлетвориться, но так как мы с вами пытливые умы с очумелыми ручками - будем делать всё по своему. Создаём новый домен:

# openstack domain create --description "OwlHost Cloud Solution" owlhost

После чего внутри домена уже можно создавать проекты. Начнём как и в инструкции с двух - сервисного и обычного:

# openstack project create --domain owlhost --description "Service Project" service
# openstack project create --domain owlhost --description "Test Project" test

Так же нам понадобится пользователь, который будет рулить нашим тестовым проектом

# openstack user create --domain owlhost --password-prompt owlbook

Вводим пароль, создаём роль и связываем всё воедино

# openstack role create test_admin
# openstack role add --project test --user owlbook test_admin

Проверяем всё, что наделали

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

# openstack token issue

На выходе должно получиться что-то вроде:

+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+                                   
| Field      | Value                                                                                                                                                                                   |                                   
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+                                   
| expires    | 2019-05-05T07:09:11+0000                                                                                                                                                                |                                   
| id         | gAAAAABczn4Hg8QctV5FvMbxJeOFB5f6w4IP-O1SMW_nIUE33cXdlqPtoGfbZ-IQt_mu3Lct-arUTtxMaaGUkqAdhvrPGQcXiemmlaAGxDSuvKEs1qCa8Sea_zoK5lDbka9iJ013zTcWmsC08k7QazgndQaWpe5gxm_6FV9Gj6krYZi28hMEpxc |                                   
| project_id | 00f4415a702044bbaedbf81cbe1668cf                                                                                                                                                        |                                   
| user_id    | f23a149197af41d598821ec791f21e01                                                                                                                                                        |                                   
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 

Создадим ещё один файлик, поправив в нём креды для нашего regular пользователя

/etc/creds.n
export OS_USERNAME=owlbook
export OS_PASSWORD=REFULAR_PASSWORD
export OS_PROJECT_NAME=test
export OS_USER_DOMAIN_NAME=owlhost
export OS_PROJECT_DOMAIN_NAME=owlhost
export OS_AUTH_URL=http://mgt1.cloud.ow1.in:5000/v3
export OS_IDENTITY_API_VERSION=3

Сделаем source /etc/creds.n и снова попробуем выписать токен. Если на выходе получим выхлоп подобный предыдущему - то всё успешно работает. Поздравляю.

1)
к слову официальная документация некоторые вещи подразумевает из коробки
2)
ну слишком же просто и доступно
3)
пару часов я на это конечно потратил