Camminando lungo il percorso di miglioramento dell'infrastruttura, ho deciso di affrontare una questione antica e complessa: fornire senza ulteriori sforzi la possibilità ai colleghi (sviluppatori, tester, amministratori, ecc.) di gestire autonomamente le proprie macchine virtuali in ovirt. In ovirt ci sono diversi componenti da configurare per risolvere la mia questione: l'interfaccia web, la console noVNC e il caricamento delle immagini dei dischi.
Non ho trovato i pulsanti "Fallo Fantastico", quindi mostro quali manopole ho ruotato per risolvere questo compito. Istruzioni complete qui sotto:

DISCLAIMER:
Prima di iniziare, vorrei attirare l'attenzione sul fatto che, per qualche ragione a me sconosciuta, i domini dell'infrastruttura vengono creati in zone private lan, local, e così via.
Non so cosa impedisca l'uso del dominio dell'organizzazione in una zona pubblica. Ad esempio, invece del dominio Alex-GLuck-Awesome-Company.local, si può tranquillamente usare il dominio del sito aziendale Alex-GLuck-Awesome-Company.com.
Se temete di non riuscire a tenere traccia dei domini nella vostra organizzazione e che questo possa causare dei problemi, per soli 100 rubli all'anno potete acquistare un dominio separato per l'infrastruttura aglac.com.
Perché è vantaggioso utilizzare domini in zone pubbliche:
1. All'interno della vostra organizzazione compaiono servizi che accedono allo spazio pubblico: vpn, scambio di file (seafile, nextcloud) e altri. Configurare la crittografia del traffico su tali servizi di solito sembra essere un lavoro mal fatto, e non ci proteggeremo da MitM, perché è complicato (in realtà non lo è).
Oppure nel vostro ufficio avete un indirizzo del servizio, mentre dall'esterno ne avete un altro, e queste connessioni devono essere mantenute, il che consuma le nostre risorse limitate di specialisti. Inoltre, i dipendenti devono memorizzare indirizzi diversi, il che è scomodo.
2. Potete utilizzare centri di certificazione gratuiti per la crittografia dei vostri servizi interni.
Un proprio PKI è un servizio che deve essere mantenuto, 100 rubli all'anno per la possibilità di utilizzare PKI da centri di certificazione gratuiti coprono ampiamente il tempo dei dipendenti che potrebbero dedicarlo ad altre attività.
3. Utilizzando il proprio centro di certificazione, ostacolerete i vostri dipendenti e colleghi remoti che desiderano lavorare con BYOD (portano i propri laptop, telefoni, tablet) e non potrete gestire i loro dispositivi. Portano Mac, Linux, Android, iOS, Windows: non ha alcun senso sostenere uno zoo del genere.
Certo, ci sono eccezioni, e le banche con altri severi sistemi aziendali che hanno politiche di sicurezza consolidate non saranno mai in grado di migliorare il servizio per i loro dipendenti.
Per loro ci sono centri di certificazione a pagamento, che possono firmare il loro certificato CA per una certa somma (cercare "root signing service").
Ci sono anche altre ragioni per cui è più vantaggioso utilizzare un dominio pubblico (la cosa più importante è che appartenga a voi), ma l'articolo non tratta di questo.
La sostanza, insomma…
ATTENZIONE! Se aggiungete un certificato CA di Let’s Encrypt all'elenco dei certificati affidabili per ovirt, questo potrebbe influire sulla sicurezza dei vostri sistemi!
La prima cosa a cui prestare attenzione è che esporre le interfacce di ovirt a Internet è una cattiva pratica, poiché non ha alcun senso pratico e crea ulteriori minacce alla sicurezza.
Di conseguenza, è necessario ottenere un certificato su uno dei nostri host bastione, dopodiché trasferire il certificato e la chiave al nostro host con ovirt-engine.
Aggiungiamo l'indirizzo esterno del nostro host bastione nel DNS con il nostro nome di ovirt ovirtengine.example.com, l'installazione di certbot e nginx la lascerò da parte (come farlo è già stato descritto su Habr).
Configuriamo nginx versione >=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;
# Consenti al server di allegare le risposte OCSP, riducendo il tempo di caricamento delle pagine per gli utenti.
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
location / {
return 444;
}
}
Poi otteniamo il nostro certificato e la chiave:
certbot certonly --nginx -d ovirtengine.example.com
Archiviando il nostro certificato e la chiave:
tar Phczf /tmp/ovirtengine.example.com.tgz /etc/letsencrypt/live/ovirtengine.example.com
Scarichiamo l'archivio dall'host bastione e lo carichiamo sul nostro ovirt-engine:
scp bastion-host:/tmp/ovirtengine.example.com.tgz /tmp/
scp /tmp/ovirtengine.example.com.tgz ovirtengine.example.com:/
Passiamo all'obiettivo
Successivamente, estraiamo il nostro archivio e creiamo collegamenti simbolici per semplificare la comprensione del sistema di posizionamento dei file:
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
Configuriamo il pki integrato in ovirt in modo che venga utilizzato il keystore dei certificati java (openjdk) per la verifica dei certificati:
cat < /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
Convertiamo il CA di let’s encrypt in formato der e lo aggiungiamo al keystore dei certificati java trust store di ovirt (questo è un contenitore in cui si trova l'elenco dei certificati, un sistema utilizzato in 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
Modifichiamo le impostazioni SSL per Apache, aggiungendo un parametro per supportare i symlink e rimuovendo il parametro per il CA, che controlla i certificati (di default utilizzerà il set di CA fidati del sistema per la verifica):
sed -r -i 's|^(SSLCACertificateFile.*)|#1|g' /etc/httpd/conf.d/ssl.conf
sed -r -i '0,/^(#?SSLCACertificateFile.*)/ s//1nOptions FollowSymlinks/' /etc/httpd/conf.d/ssl.conf
Dopodiché, facciamo il backup dei file originali generati automaticamente tramite PKI di ovirt, e sostituiamo i symlink con i file di 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
Ripristiniamo i contesti SElinux sui file e riavviamo i nostri servizi (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 — server web apache
ovirt-engine — interfaccia web di ovirt
ovirt-imageio-proxy — demone per il caricamento delle immagini dei dischi
ovirt-websocket-proxy — servizio per il funzionamento della console noVNC
Tutto quanto sopra è stato testato sulla versione 4.2 di ovirt.
Auto-aggiornamento dei certificati su ovirt
Secondo le buone pratiche di sicurezza, non dovrebbe esserci connessione tra l'host bastione e ovirt, e il certificato viene emesso solo per 3 mesi. Qui nasce il punto controverso su come viene implementato l'aggiornamento dei certificati.
Ho un playbook Ansible che viene eseguito su Foreman ogni giorno alle 5 del mattino secondo la pianificazione. Questo playbook accede a ovirt, verifica la scadenza del certificato e se mancano meno di 5 giorni alla scadenza, accede all'host bastione e avvia l'aggiornamento del certificato.
Dopo l'aggiornamento del certificato, archivia la cartella con i file, scarica sull'host di Foreman e la decomprime sull'host di ovirt. Dopodiché ripristina i contesti SElinux sui file e riavviamo i nostri servizi.
Fonte: habr.com
