RHEL 8 Beta pakub arendajatele palju uusi vĂ”imalusi, mille loetlemine vĂ”iks vĂ”tta lehekĂŒlgi, kuid uut on alati parem Ă”ppida praktikas. SeetĂ”ttu soovitame allpool lĂ€bida praktilise harjutuse, et luua rakenduste infrastruktuur Red Hat Enterprise Linux 8 Beta baasil.

VĂ”tame aluseks Python'i, arendajate seas populaarse programmeerimiskeele, kombinatsiooni Django ja PostgreSQL, mis on ĂŒsna levinud zest rakenduste loomisel, ning konfigureerime RHEL 8 Beta töötamiseks nende keskkondadega. Peale selle lisame veel paar (mitte saladuslikku) koostisosade.
Testimiskeskkond muutub, sest on huvitav uurida automatiseerimise vĂ”imalusi, töötada konteineritega ja proovida keskkondi, kus on mitu serverit. Uue projekti alustamiseks vĂ”ib alustada vĂ€ikese ja lihtsa prototĂŒĂŒbi loomisega kĂ€sitsi â nii on vĂ”imalik nĂ€ha, mis tĂ€pselt peaks juhtuma ja kuidas toimib koostegevus, ning seejĂ€rel liikuda automatiseerimise ja keerukamate konfigureerimise loomise suunas. TĂ€na rÀÀgime sellise prototĂŒĂŒbi loomise protsessist.
Alustame RHEL 8 Beta VM pildi juurutamisega. VĂ”ib installida virtuaalse masina nullist vĂ”i kasutada KVM kĂŒlalispildi, mis on saadaval koos Beta tellimusega. KĂŒlalispildi kasutamisel peab seadistama virtuaalse CD, mis sisaldab meetaandmeid ja kasutajandmeid pilveiniitsialiseerimiseks (cloud-init). Diskistruktuuri vĂ”i saadaval olevate paketiga ei pea midagi erilist tegema, sobib igasugune konfiguratsioon.
Vaadakem kogu protsessi lÀhemalt.
Django installimine
Uueimaga Django versiooniga on vajalik virtuaalne keskkond (virtualenv) Python 3.5 vÔi uuema versiooniga. Beta mÀrkustes oleme nÀinud, et Python 3.6 on saadaval, vaatame, kas see tÔepoolest nii on:
[cloud-user@8beta1 ~]$ python
-bash: python: kÀsku ei leitud
[cloud-user@8beta1 ~]$ python3
-bash: python3: kÀsku ei leitud
Red Hat kasutab Pythonit aktiivselt RHEL-i sĂŒsteemide tööriistana, seega, miks saadakse selline tulemus?
As it turns out, many developers using Python are still considering a transition from Python 2 to Python 2, while Python 3 is under active development and new versions are constantly being released. Therefore, to meet the need for stable system tools and simultaneously offer users access to various new versions of Python, the system Python has been moved to a new package, allowing the installation of both Python 2.7 and 3.6. More detailed information about the changes and why this was done can be found in the publication on (Langdon White).
Thus, to obtain a functioning Python, it is necessary to install just two packages, while python3-pip will be pulled in as a dependency.
sudo yum install python36 python3-virtualenv
Why not use direct calls to the module as Langdon suggests, and not install pip3? Keeping in mind the upcoming automation, it is known that Ansible requires pip to be installed, as the pip module does not support virtual environments (virtualenvs) with a custom pip executable.
Having a working python3 interpreter at your disposal, you can continue the Django installation process and obtain a functioning system along with our other components. There are many implementation options available online. Here is one version presented, but users can use their own processes.
The versions of PostgreSQL and Nginx that are available in RHEL 8 by default will be installed using Yum.
sudo yum install nginx postgresql-server
PostgreSQL will require psycopg2, but it needs to be available only in the virtualenv environment, so we will install it using pip3 along with Django and Gunicorn. But first, we need to set up virtualenv.
There is always a lot of debate about the proper choice of installation location for Django projects, but when doubts arise, one can always refer to the Linux Filesystem Hierarchy Standard. In particular, the FHS states that /srv is used for: "storing data specific to a particular node â data served by the system, such as data and scripts of web servers, data stored on FTP servers, as well as repositories of version control systems (introduced in FHS-2.3 in 2004)."
See on just meie juhtum, seega paneme kÔik vajalikud asjad kausta /srv, mille omanikuks on meie rakenduse kasutaja (cloud-user).
sudo mkdir /srv/djangoapp
sudo chown cloud-user:cloud-user /srv/djangoapp
cd /srv/djangoapp
virtualenv django
source django/bin/activate
pip3 install django gunicorn psycopg2
./django-admin startproject djangoapp /srv/djangoapp
PostgreSQL ja Django seadistamine ei ole keeruline: loome andmebaasi, loome kasutaja, seadistame Ă”igused. On ĂŒks asi, mida tuleb meeles pidada PostgreSQL algse installimise juures â see on skript postgresql-setup, mis paigaldatakse koos paketiga postgresql-server. See skript aitab tĂ€ita pĂ”hiĂŒlesandeid, mis on seotud andmebaasi klastrite haldamisega, nĂ€iteks klastrite algatamine vĂ”i vĂ€rskendamise protsess. Uue PostgreSQL instantsi seadistamiseks RHEL sĂŒsteemis peame kĂ€ivitama kĂ€su:
sudo /usr/bin/postgresql-setup -initdb
PĂ€rast seda saame PostgreSQL kĂ€ivitada systemd'ga, luua andmebaasi ja seadistada projekti Django's. Ăra unusta PostgreSQL'i taaskĂ€ivitada pĂ€rast muudatuste tegemist kliendi autentimise konfiguratsioonifailis (tavaliselt pg_hba.conf) rakenduse kasutaja parooli salvestamise seadistamiseks. Kui kohtate muid raskusi, veenduge, et IPv4 ja IPv6 seaded on muudetud failis pg_hba.conf.
systemctl enable --now postgresql
sudo -u postgres psql
postgres=# create database djangoapp;
postgres=# create user djangouser with password 'qwer4321';
postgres=# alter role djangouser set client_encoding to 'utf8';
postgres=# alter role djangouser set default_transaction_isolation to 'read committed';
postgres=# alter role djangouser set timezone to 'utc';
postgres=# grant all on DATABASE djangoapp to djangouser;
postgres=# q
Failis /var/lib/pgsql/data/pg_hba.conf:
# IPv4 local connections:
host all all 0.0.0.0/0 md5
# IPv6 local connections:
host all all ::1/128 md5
Failis /srv/djangoapp/settings.py:
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '{{ db_name }}',
'USER': '{{ db_user }}',
'PASSWORD': '{{ db_password }}',
'HOST': '{{ db_host }}',
}
}
PĂ€rast settings.py faili konfigureerimist projektis ja andmebaasi konfiguratsiooni seadistamist saame kĂ€ivitada arendusserveri, et veenduda, et kĂ”ik toimib. PĂ€rast arendusserveri kĂ€ivitamist on hea luua admin kasutaja, et testida andmebaasi ĂŒhendust.
./manage.py runserver 0.0.0.0:8000
./manage.py createsuperuser
WSGI? Mis see on?
Arendusserver on kasulik testimiseks, kuid rakenduse töötamiseks tuleb seadistada vastavad server ja proksi Web Server Gateway Interface (WSGI) jaoks. On mitmeid levinud kombinatsioone, nÀiteks Apache HTTPD koos uWSGI-ga vÔi Nginx koos Gunicorniga.
Web Server Gateway Interface'i ĂŒlesanne on suunata pĂ€ringud edasi veebiserver Pythoni veebiraamistikule. WSGI on midagi, mis pĂ€rineb Ă”udse mineviku ajast, kui olid kasutusel CGI mehhanismid, ja tĂ€napĂ€eval on WSGI praktiliselt standard, sĂ”ltumata kasutatavast veebiserverist vĂ”i Pythoni raamistikust. Kuid malakaine laialdase leviku tĂ”ttu on siiski palju nĂŒansse nende raamistikudega töötamisel ja palju valikuvĂ”imalusi. Sel juhul pĂŒĂŒame seadistada Gunicorni ja Nginxi suhtlemise soketi kaudu.
Kuna mĂ”lemad komponendid on installitud samale serverile, proovime kasutada vĂ”rgu soketi asemel UNIX soketti. Kuna suhtlemiseks on igal juhul vaja soketti, proovime astuda veel ĂŒhe sammu ja seadistada Gunicorni soketi aktiveerimine systemd kaudu.
Soketiga aktiveeritavate teenuste loomise protsess on ĂŒsna lihtne. Esiteks luuakse unit-fail, mis sisaldab direktiivi ListenStream, mis nĂ€itab punkti, kus UNIX sokett luuakse, seejĂ€rel â teenuse unit-fail, mille direktiiv Requires nĂ€eb ette soketi unit-faili. SeejĂ€rel jÀÀb teenuse unit-failis lihtsalt kutsuda Gunicorn virtuaalsest keskkonnast ja luua WSGI seotus UNIX soketi ja Django rakenduse jaoks.
Siin on mÔned nÀidised unit-failidest, mida saab aluseks vÔtta. Esiteks seadistame soketi.
[Unit]
Description=Gunicorn WSGI sokett
[Socket]
ListenStream=\/run\/gunicorn.sock
[Install]
WantedBy=sockets.target
NĂŒĂŒd on vaja seadistada Gunicorni deemon.
[Unit]
Description=Gunicorn deemon
Requires=gunicorn.socket
After=network.target
[Service]
User=cloud-user
Group=cloud-user
WorkingDirectory=\/srv\/djangoapp
ExecStart=\/srv\/djangoapp\/django\/bin\/gunicorn
âaccess-logfile -
âworkers 3
âbind unix:gunicorn.sock djangoapp.wsgi
[Install]
WantedBy=multi-user.target
Nginxi jaoks on piisav lihtsalt luua pöördiste konfiguratsioonifailid ja seadistada vÀlistatud sisu salvestamise kataloog, kui kasutate seda. RHEL-is asuvad Nginxi konfiguratsioonifailid \/etc\/nginx\/conf.d. Saate kopeerida jÀrgmise nÀite faili \/etc\/nginx\/conf.d\/default.conf ja kÀivitada teenuse. Veenduge, et olete mÀÀranud server_nimi vastavalt oma hosti nimele.
server {
listen 80;
server_name 8beta1.example.com;
location = \/favicon.ico { access_log off; log_not_found off; }
location \/static\/ {
root \/srv\/djangoapp;
}
location \/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http:\/\/unix:\/run\/gunicorn.sock;
}
}
KÀivitage Gunicorni ja Nginxi sokett systemd abil, ja vÔite alustada testimist.
Bad Gateway viga?
Kui sisenete aadressi brauserisse, saate tÔenÀoliselt vea 502 Bad Gateway. See vÔib olla tingitud valesti seadistatud UNIX-soketi Ôigustest vÔi keerukamatest probleemidest, mis on seotud juurdepÀÀsu haldamisega SELinuxis.
Nginx'i vealogis vÔib sageli leida sellise joone:
2018/12/18 15:38:03 [crit] 12734#0: *3 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.122.1, server: 8beta1.example.com, request: "GET / HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/", host: "8beta1.example.com"
Kui testida Gunicorn'i otse, saame tĂŒhja vastuse.
curl âunix-socket /run/gunicorn.sock 8beta1.example.com
Vaatame, miks see juhtub. Kui avame logi, nÀeme tÔenÀoliselt, et probleem on seotud SELinuxiga. Kuna meil on kÀivitatud teenus, mille jaoks ei ole loodud oma poliitikat, tÀhistatakse seda kui init_t. Kontrollime seda teooriat praktikas.
sudo setenforce 0
KĂ”ik see vĂ”ib tekitada kriitikat ja veretuks pisaraid, kuid see on vaid prototĂŒĂŒbi silumine. LĂŒlitame kontrolli vĂ€lja, et veenduda, et probleem on tĂ”epoolest selles, pĂ€rast mida paneme kĂ”ik tagasi paika.
Brauseris lehte uuendades vÔi meie curl'i kÀsku uuesti kÀivitades nÀeme Django testlehte.
Nii et, veendudes, et kĂ”ik töötab ja muid Ă”iguse probleeme pole, lĂŒlitame SELinuxi taas sisse.
sudo setenforce 1
Siin ei rÀÀgita audit2allow'st ja poliitikate loomise protsessist, mis pĂ”hinevad teadaannete sepolgen'i abil, kuna hetkel ei ole reaalset Django rakendust, seega pole ka tĂ€ielikku kaarti sellest, millele Gunicorn vĂ”ib juurdepÀÀsu taotleda ja millele see juurdepÀÀs peab olema keelatud. Seega on vajalik, et SELinux töötaks sĂŒsteemi kaitsmiseks, samas lubades rakendusel kĂ€ivituda ja logida auditi sĂ”numeid, et hiljem saaks nende pĂ”hjal luua tĂ”elise poliitika.
Lubatud domeenide mÀÀramine (permissive domains)
Paljud ei ole kuulnud lubatud domeenidest SELinuxis, kuid need pole midagi uut. Paljud on isegi nendega töötanud, sellest aru saamata. Kui poliitika luuakse audititeadete pÔhjal, esindab loodud poliitika lubatud domeeni. Proovime luua lihtsaimat lubavat poliitikat.
Gunicorn'i konkreetse lubatud domeeni loomiseks on vajalik poliitika ning vastavaid faile tuleb mÀrgistada. Samuti on vajalikud tööriistad uute poliitikate koostamiseks.
sudo yum install selinux-policy-devel
Lubatud domeenide mehhanism on suurepĂ€rane tööriist probleemide tuvastamiseks, eriti kui tegemist on kohandatud rakenduse vĂ”i rakendustega, mis on tarnitud juba loodud poliitikateta. Antud juhul on Gunicorn'i lubatud domeeni poliitika maksimaalselt lihtne â kuulutame vĂ€lja pĂ”hiliigi (gunicorn_t), mÀÀrame tĂŒĂŒbi, mida kasutame mitmete tĂ€itmisfailide mĂ€rgistamiseks (gunicorn_exec_t), ja seejĂ€rel seadistame ĂŒlemineku (transition) sĂŒsteemile, et Ă”igesti mĂ€rgistada töötavaid protsesse. Viimane rida mÀÀrab poliitika vaikimisi lubatuks selle laadimise hetkeks.
gunicorn.te:
policy_module(gunicorn, 1.0)
type gunicorn_t;
type gunicorn_exec_t;
init_daemon_domain(gunicorn_t, gunicorn_exec_t)
permissive gunicorn_t;
Selle poliitikafaili saab kompileerida ja sĂŒsteemi lisada.
make -f /usr/share/selinux/devel/Makefile
sudo semodule -i gunicorn.pp
sudo semanage permissive -a gunicorn_t
sudo semodule -l | grep permissive
Kontrollime, kas SELinux ei blokeeri midagi muud, peale selle, mida meie tundmatu deemon kasutab.
sudo ausearch -m AVC
type=AVC msg=audit(1545315977.237:1273): avc: denied { write } for pid=19400 comm="nginx" name="gunicorn.sock" dev="tmpfs" ino=52977 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0
SELinux ei luba Nginx'il kirjutada andmeid Unix socket'i, mida Gunicorn kasutab. Tavalistes olukordades hakatakse poliitikaid muutma, kuid ees on veel teised ĂŒlesanded. Samuti on vĂ”imalik muuta domeeni seadeid, muutes selle piirangute domeenist lubatud domeeniks. NĂŒĂŒd kanname httpd_t lubatud domeeni. See tagab Nginx'i vajaliku juurdepÀÀsu ning saame jĂ€tkata tĂ”rkeotsingut.
sudo semanage permissive -a httpd_t
Nii, kui Ă”nnestub sĂ€ilitada SELinux'i kaitse (pĂ€riselt ei tohiks projekti jĂ€tta SELinux'i piirangute reĆŸiimi) ja lubatud domeenid on laaditud, on vajalik vĂ€lja selgitada, mida tuleb mĂ€rgistada kui gunicorn_exec_t, et kĂ”ik uuesti Ă”igesti töötaks. Proovime kĂŒlastada veebisaiti, et nĂ€ha uusi juurdepÀÀsu piiranguid.
sudo ausearch -m AVC -c gunicorn
NĂ€eme mitmeid teateid, mis sisaldavad âcomm=«gunicorn»â, mis teevad erinevaid toiminguid failidega aadressil /srv/djangoapp, seega on ilmselge, et see on ĂŒks kĂ€sk, mida tasub mĂ€rgistada.
Kuid lisaks ilmub sÔnum nagu jÀrgmine:
type=AVC msg=audit(1545320700.070:1542): avc: denied { execute } for pid=20704 comm="(gunicorn)" name="python3.6" dev="vda3" ino=8515706 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0
Kui vaatate gunicorni teenuse staatust vĂ”i kĂ€ivitate kĂ€su ps, siis ei ilmu kĂ€ivitatud protsesside hulka midagi. Tundub, et gunicorn ĂŒritab pÀÀseda meie virtualenv'i Python'i tĂ”lgile, vĂ”ib-olla tööscriptide (workers) kĂ€ivitamiseks. SeetĂ”ttu mĂ€rgistame praegu need kaks tĂ€itmisfaili ja kontrollime, kas suudame avada meie testimislehe Django.
chcon -t gunicorn_exec_t /srv/djangoapp/django/bin/gunicorn /srv/djangoapp/django/bin/python3.6
Gunicorn teenuse uuesti kÀivitamine on vajalik, et valida uus mÀrgis. VÔite selle kohe uuesti kÀivitada vÔi stoppida teenuse ja lasta sokkel selle kÀivitada, kui avate lehe brauseris. Veenduge, et protsessid on saanud Ôiged mÀrgised, kasutades ps.
ps -efZ | grep gunicorn
Ărge unustage seejĂ€rel luua korralik SELinux poliitika!
Kui vaatate praegu AVC teateid, siis viimane sĂ”num sisaldab permissive=1 kĂ”igi rakenduse kohta ja permissive=0 kogu ĂŒlejÀÀnud sĂŒsteemi jaoks. Kui mĂ”ista, millist ligipÀÀsu tegelik rakendus vajab, on vĂ”imalik kiiremini leida optimaalseid lahendusi selliste probleemide lahendamiseks. Kuid seni on parem, et sĂŒsteem oleks kaitstud, et saada arusaadavat ja kasutatavat auditit Django projekti kohta.
sudo ausearch -m AVC
Saime hakkama!
Ilmus töötav Django projekt Nginxi ja Gunicorni WSGI-ga. Oleme seadistanud Python 3 ja PostgreSQL 10 RHEL 8 Beta hoidlatest. NĂŒĂŒd on aeg edasi liikuda ja luua (vĂ”i lihtsalt juurutada) Django rakendusi vĂ”i uurida teisi RHEL 8 Beta saadaval olevaid tööriistu seadistamise protsessi automatiseerimiseks, jĂ”udluse suurendamiseks vĂ”i isegi selle konfiguratsiooni konteineriseerimiseks.
Allikas: habr.com
