Как подружить Ovirt и Let's Encrypt

Шагая по пути улучшения инфраструктуры, я решил добить древний и мучительный вопрос — без лишних телодвижений предоставлять возможность коллегам (разработчикам, тестировщикам, админам, etc) самостоятельно управлять своими виртуалками в ovirt’е. В ovirt есть несколько компонентов, которые надо настроить для решения моего вопроса: сам веб интерфейс, noVNC консоль и заливка образов дисков.

Кнопки «Сделать Зашибись» я не нашёл, поэтому показываю какие ручки я крутил, чтобы решить данную задачу. Полная инструкция под катом:

pvuoaxsmb0cnk7ifn-sjjh2aal0.jpeg

DISCLAIMER:


Перед началом хотел бы обратить внимание, что по какой-то неизвестной мне причине домены инфраструктуры создаются в частных зонах lan, local, и так далее.

Что мешает использовать домен организации в публичной зоне мне неизвестно. К примеру, вместо домена Alex-GLuck-Awesome-Company.local, можно смело использовать домен для сайта компании Alex-GLuck-Awesome-Company.com.

Если вы боитесь, что не сможете уследить за доменами в своей организации, и это что-нибудь сломает, то за скромные 100 рублей в год можете взять отдельный домен для инфраструктуры aglac.com.

Почему выгодней использовать домены в публичных зонах:

1. У вас внутри организации появляются сервисы выходящие в публичное пространство: впн, обмен файлами (seafile, nextcloud) и другие. Настраивать шифрование трафика на таких сервисах обычно выглядит как тяп-ляп, и от MitM защищаться мы не будем, потому что сложно (на самом деле нет).

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

2. Вы можете использовать бесплатные центры сертификации для шифрования ваших внутренних сервисов.

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

3. При использовании собственного центра сертификации вы будете вставлять палки в колёса вашим удалённым сотрудникам и коллегам, которые хотят работать с BYOD (приносят свои ноуты, телефон, планшеты) и вы не можете управлять их устройствами. Они приносят маки, линуксы, андройды, IOS, винду — поддерживать такой зоопарк нет никакого смысла.

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

Для них есть платные центры сертификации, которые за определённую сумму могут подписать их CA сертификат (гуглить «root signing service»).

Есть и другие причины, почему публичный домен использовать выгодней (самое главное, чтобы он принадлежал вам), но статья не об этом.

Суть, да дело…


ВНИМАНИЕ! Если вы добавите сертификат CA от Let’s Encrypt в список доверенных для ovirt’а, это может повлиять на безопасность ваших систем!

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

Следовательно получать сертификат необходимо на каком-нибудь нашем бастион-хосте, после чего переносить сертификат и ключ на наш хост с ovirt-engine.

Добавляем внешний адрес нашего бастион-хоста в днс с нашим именем овирта ovirtengine.example.com, установку certbot и nginx я оставлю за кадром (как это сделать на хабре уже описано).

Настраиваем нджинкс версии >=1.15.7

/etc/nginx/conf.d/default.conf
server {
    server_name _;
    listen 80 default_server;
    location /robots.txt { alias /usr/share/nginx/html/robots.txt; }
    location /.well-known {
        root /usr/share/nginx/html;
    }
    location / {
        return 444;
    }
}

server {
    server_name _;
    listen 443 ssl http2 default_server;
    location /robots.txt { alias /usr/share/nginx/html/robots.txt; }
    location /.well-known {
        root /usr/share/nginx/html;
    }

    ssl_certificate /etc/nginx/ssl/$ssl_server_name/fullchain.pem; 
    ssl_certificate_key /etc/nginx/ssl/$ssl_server_name/privkey.pem;

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;

    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;

    # позволяем серверу прикреплять OCSP-ответы, тем самым уменьшая время загрузки страниц у пользователей
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

    location / {
        return 444;
    }
}



Потом получаем наш сертификат и ключ:

certbot certonly --nginx -d ovirtengine.example.com


Архивируем наш сертификат и ключ:

tar Phczf /tmp/ovirtengine.example.com.tgz /etc/letsencrypt/live/ovirtengine.example.com


Скачиваем с бастион-хоста архив, заливаем на наш овирт-енжин:

scp bastion-host:/tmp/ovirtengine.example.com.tgz /tmp/
scp /tmp/ovirtengine.example.com.tgz ovirtengine.example.com:/


Переходим к цели


Далее мы распаковываем наш архив и создаём симлинки для упрощения понимания системы расположения файлов:

tar Pxzf /ovirtengine.example.com.tgz && rm -f ovirtengine.example.com.tgz
mkdir -p /etc/letsencrypt/live
ln -f -s /etc/letsencrypt/live /etc/pki/letsencrypt


Настраиваем встроенный pki в овирт, чтобы для проверки сертификатов использовалось хранилище сертификатов java (openjdk):

cat << EOF > /etc/ovirt-engine/engine.conf.d/99-setup-pki.conf 
ENGINE_HTTPS_PKI_TRUST_STORE="/etc/pki/java/cacerts"
ENGINE_HTTPS_PKI_TRUST_STORE_PASSWORD=""
EOF


Конвертируем CA от let’s encrypt’а в der формат и добавляем в хранилище сертификатов java trust store овирта (это такой контейнер, в котором находится перечень сертификатов, такая система используется в java):

openssl x509 -outform der -in /etc/pki/letsencrypt/ovirtengine.example.com/chain.pem -out /tmp/ovirtengine.example.com.chain.der
keytool -import -alias "Let's Encrypt Authority X3" -file /tmp/ovirtengine.example.com.chain.der -keystore /etc/pki/ovirt-engine/.truststore -storepass $(grep '^ENGINE_PKI_TRUST_STORE_PASSWORD' /etc/ovirt-engine/engine.conf.d/10-setup-pki.conf | cut -f 2 -d '"')
rm -f /tmp/ovirtengine.example.com.chain.der


Редактируем настройки SSL для apache, добавляем параметр для поддержки симлинков и убираем параметр для CA, которым проверять сертификаты (по умолчанию будет пользоваться системный набор доверенных CA для проверки):

sed -r -i 's|^(SSLCACertificateFile.*)|#\1|g' /etc/httpd/conf.d/ssl.conf
sed -r -i '0,/(^#?SSLCACertificateFile.*)/ s//\1\nOptions FollowSymlinks/' /etc/httpd/conf.d/ssl.conf


После чего бекапируем на всякий случай оригинальные файлы, сгенерированные через PKI ovirt’а автоматический и подменяем симлинками на файлы от Let’s Encrypt:

ln -f -s /etc/pki/letsencrypt/ovirtengine.example.com/fullchain.pem /etc/pki/ovirt-engine/apache-chain.pem
services=( 'apache' 'imageio-proxy' 'websocket-proxy' )
for i in "${services[@]}"; do
cp /etc/pki/ovirt-engine/certs/$i.cer{,."$( date +%F )".bak}
cp /etc/pki/ovirt-engine/keys/$i.key.nopass{,."$( date +%F )".bak}
ln -f -s /etc/pki/letsencrypt/ovirtengine.example.com/privkey.pem /etc/pki/ovirt-engine/keys/$i.key.nopass
ln -f -s /etc/pki/letsencrypt/ovirtengine.example.com/cert.pem /etc/pki/ovirt-engine/certs/{apache,imageio-proxy,websocket-proxy}.cer
done


Восстанавливаем SElinux контексты на файлах и перезапускаем наши сервисы (httpd, ovirt-engine, ovirt-imageio-proxy, ovirt-websocket-proxy):

restorecon -Rv /etc/pki
systemctl restart httpd ovirt-engine ovirt-imageio-proxy ovirt-websocket-proxy


httpd — веб сервер apache
ovirt-engine — веб интерфейс ovirt
ovirt-imageio-proxy — демон для загрузки образов дисков
ovirt-websocket-proxy — сервис для работы noVNC консоли

Всё выше перечисленное было проверено на версии овирта 4.2.

Автообновление сертификатов на ovirt


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

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

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

© Habrahabr.ru